Repository: jenkinsci/jenkins
File: core/src/main/java/jenkins/install/SetupWizard.java (Java)

Code before:
        updateSiteList: for (UpdateSite updateSite : Jenkins.get().getUpdateCenter().getSiteList()) {
            String updateCenterJsonUrl = updateSite.getUrl();
            String suggestedPluginUrl = updateCenterJsonUrl.replace("/update-center.json", "/platform-plugins.json");
            try {
                URLConnection connection = ProxyConfiguration.open(new URL(suggestedPluginUrl));
                
                try {
                    if(connection instanceof HttpURLConnection) {
                        int responseCode = ((HttpURLConnection)connection).getResponseCode();
                        if(HttpURLConnection.HTTP_OK != responseCode) {
                            throw new HttpRetryException("Invalid response code (" + responseCode + ") from URL: " + suggestedPluginUrl, responseCode);
                        }
                    }
                    
                    String initialPluginJson = IOUtils.toString(connection.getInputStream(), StandardCharsets.UTF_8);
                    initialPluginList = JSONArray.fromObject(initialPluginJson);
                    break updateSiteList;
                } catch(Exception e) {
                    // not found or otherwise unavailable
                    LOGGER.log(Level.FINE, e.getMessage(), e);
                    continue updateSiteList;
                }
            } catch(Exception e) {
                LOGGER.log(Level.FINE, e.getMessage(), e);
            }
        }
        if (initialPluginList == null) {
            // fall back to local file
            try {
                ClassLoader cl = getClass().getClassLoader();
                URL localPluginData = cl.getResource("jenkins/install/platform-plugins.json");
                String initialPluginJson = IOUtils.toString(localPluginData.openStream(), StandardCharsets.UTF_8);
                initialPluginList =  JSONArray.fromObject(initialPluginJson);
            } catch (Exception e) {
                LOGGER.log(Level.SEVERE, e.getMessage(), e);
            }
        }
        return initialPluginList;
    }

    /**
     * Get the platform plugins added in the version range
     */
    /*package*/ JSONArray getPlatformPluginsForUpdate(VersionNumber from, VersionNumber to) {
        Jenkins jenkins = Jenkins.get();
        JSONArray pluginCategories = JSONArray.fromObject(getPlatformPluginList().toString());
        for (Iterator<?> categoryIterator = pluginCategories.iterator(); categoryIterator.hasNext();) {
            Object category = categoryIterator.next();
            if (category instanceof JSONObject) {
                JSONObject cat = (JSONObject)category;
                JSONArray plugins = cat.getJSONArray("plugins");

Review comment (suggestion):
Should it have a separate flag for update centers which do not sign the platform services file but sign other artifacts?
In such case we may end up in regressions

Code after:
        Jenkins.get().checkPermission(Jenkins.ADMINISTER);
        JSONArray initialPluginList = null;
        updateSiteList: for (UpdateSite updateSite : Jenkins.get().getUpdateCenter().getSiteList()) {
            String updateCenterJsonUrl = updateSite.getUrl();
            String suggestedPluginUrl = updateCenterJsonUrl.replace("/update-center.json", "/platform-plugins.json");
            VersionNumber version = Jenkins.getVersion();
            if (version != null && (suggestedPluginUrl.startsWith("https://") || suggestedPluginUrl.startsWith("http://"))) {
                // Allow remote update site to distinguish based on the current version
                // This looks a bit hacky but UpdateCenter#toUpdateCenterCheckUrl does something similar
                suggestedPluginUrl = suggestedPluginUrl + (suggestedPluginUrl.contains("?") ? "&" : "?") + "version=" + version;
            }
            try {
                URLConnection connection = ProxyConfiguration.open(new URL(suggestedPluginUrl));
                
                try {
                    String initialPluginJson = IOUtils.toString(connection.getInputStream(), StandardCharsets.UTF_8);

                    JSONObject initialPluginObject = null;

                    if(connection instanceof HttpURLConnection) {
                        int responseCode = ((HttpURLConnection)connection).getResponseCode();
                        if(HttpURLConnection.HTTP_OK != responseCode) {
                            throw new HttpRetryException("Invalid response code (" + responseCode + ") from URL: " + suggestedPluginUrl, responseCode);
                        }

                        if (DownloadService.signatureCheck) {
                            /* If the platform-plugins.json file was obtained remotely, assume that it's a JSONObject and perform a signature check on it */
                            initialPluginObject = JSONObject.fromObject(initialPluginJson);
                            final FormValidation result = updateSite.verifySignatureInternal(initialPluginObject);
                            if (result.kind != FormValidation.Kind.OK) {
                                LOGGER.log(Level.WARNING, "Ignoring remote platform-plugins.json: " + result.getMessage());
                                throw result;
                            }
                        }
                    }

                    /*
                        The initial version of this code expected platform-plugins.json to be an array.
                        This structure does not work when we want to add a signature block, so a wrapper object is also supported.
                        In that case, the original array is expected to be in the 'categories' key.
                     */
                    if (initialPluginObject != null) {
                        initialPluginList = initialPluginObject.getJSONArray("categories");
                    } else {
                        try {
                            initialPluginList = JSONArray.fromObject(initialPluginJson);
                        } catch (Exception ex) {
                            /* Second attempt: It's not a remote file, but still wrapped */
                            initialPluginList = JSONObject.fromObject(initialPluginJson).getJSONArray("categories");
                        }
                    }