{"record":{"id":"8a73588cce414b93","repo":"HMCL-dev/HMCL","slug":"redirected-to-not-http-uri-target","errorCode":null,"errorMessage":"Redirected to not http URI: <target>","messagePattern":"Redirected to not http URI: <target>","errorType":"exception","errorClass":"java.io.IOException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/task/FetchTask.java","lineNumber":363,"sourceCode":"                                }\n                            }\n\n                            if (responseCode >= 300 && responseCode <= 308 && responseCode != 306 && responseCode != 304) {\n                                if (redirects == null) {\n                                    redirects = new ArrayList<>();\n                                } else if (redirects.size() >= 20) {\n                                    throw new IOException(\"Too much redirects\");\n                                }\n\n                                String location = connection.getHeaderField(\"Location\");\n                                if (StringUtils.isBlank(location))\n                                    throw new IOException(\"Redirected to an empty location\");\n\n                                URI target = currentURI.resolve(NetworkUtils.encodeLocation(location));\n                                redirects.add(target);\n\n                                if (!NetworkUtils.isHttpUri(target))\n                                    throw new IOException(\"Redirected to not http URI: \" + target);\n\n                                currentURI = target;\n                            } else {\n                                keepConnection = true;\n                                break;\n                            }\n                        } finally {\n                            if (!keepConnection && connection != null) {\n                                closeHttpConnection(connection);\n                                connection = null;\n                            }\n                        }\n                    } while (true);\n\n                    InputStream inputStream = null;\n                    boolean responseBodyConsumed = false;\n                    try {\n                        if (resumeRequested && responseCode == 416) {","sourceCodeStart":345,"sourceCodeEnd":381,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FetchTask.java#L345-L381","documentation":"After resolving a redirect's Location header, FetchTask.downloadHttp() validates the resulting URI is an HTTP(S) URI before continuing. This IOException is thrown when a redirect points to a non-http(s) scheme (e.g. ftp:, file:, or a malformed URI), which the downloader refuses to follow for safety.","triggerScenarios":"A server's Location header redirects to ftp://, file://, data:, or an unparseable URI — often from misconfigured redirects or malicious/open-redirect endpoints.","commonSituations":"Legacy mirrors redirecting to FTP; misconfigured CDNs emitting relative paths that resolve to invalid URIs; security-sensitive environments where redirect targets must be constrained.","solutions":["Locate the redirecting host and correct its Location header to an http(s) URL","Use the final direct http(s) URL as the download source","Treat the host as untrusted (possible open redirect) and blocklist it","Catch the IOException and route the download through a different mirror"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"URI location = currentURI.resolve(NetworkUtils.encodeLocation(rawLocation));\nif (!NetworkUtils.isHttpUri(location))\n    throw new IllegalArgumentException(\"Refusing non-http redirect: \" + location);","typeGuard":"static boolean isSafeRedirect(URI target) {\n    String s = target.getScheme();\n    return \"http\".equals(s) || \"https\".equals(s);\n}","tryCatchPattern":"try {\n    fetchTask.run();\n} catch (IOException e) {\n    if (e.getMessage().startsWith(\"Redirected to not http URI\")) blocklistHostAndRetry();\n    else throw e;\n}","preventionTips":["Restrict redirects to same-host or allow-listed hosts","Treat non-http redirects as a security signal and log them","Use direct final URLs from trusted indexes when possible"],"tags":["http","redirect","security","url"],"backgroundTag":"invalid-url","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}