{"record":{"id":"b48abca659e16e8d","repo":"jeecgboot/JeecgBoot","slug":"url-b48abc","errorCode":null,"errorMessage":"非法URL：格式错误","messagePattern":"非法URL：格式错误","errorType":"validation","errorClass":"JeecgBootException","httpStatus":null,"severity":"warning","filePath":"jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/filter/SsrfFileTypeFilter.java","lineNumber":330,"sourceCode":"    //update-begin---author:zhangdaihao ---date:2026-04-15  for：【issues/9553】修复二次SSRF漏洞，对HTTP下载URL进行安全校验-----------\n    /**\n     * 校验HTTP(S) URL，防止SSRF攻击（最小化拦截，只挡真正危险的目标）。\n     * 规则：\n     * 1. 仅允许 http / https 协议；\n     * 2. 解析主机IP，拒绝 loopback（127.x / ::1）和 link-local（169.254.x，含云元数据 169.254.169.254 / fe80:）；\n     * 注意：RFC1918 私网段（10/172.16/192.168）允许通过，兼容企业内网 MinIO/OSS/文件服务等合法用途。\n     *\n     * @param fileUrl HTTP(S) URL\n     */\n    public static void checkSsrfHttpUrl(String fileUrl) {\n        if (StringUtils.isBlank(fileUrl)) {\n            throw new JeecgBootException(\"非法URL：地址为空\");\n        }\n        URI uri;\n        try {\n            uri = new URI(fileUrl);\n        } catch (URISyntaxException e) {\n            throw new JeecgBootException(\"非法URL：格式错误\");\n        }\n        String scheme = uri.getScheme();\n        if (scheme == null || !(scheme.equalsIgnoreCase(\"http\") || scheme.equalsIgnoreCase(\"https\"))) {\n            throw new JeecgBootException(\"非法URL：仅允许 http / https 协议\");\n        }\n        String host = uri.getHost();\n        if (StringUtils.isBlank(host)) {\n            throw new JeecgBootException(\"非法URL：主机名为空\");\n        }\n        // 去掉 IPv6 的中括号\n        if (host.startsWith(\"[\") && host.endsWith(\"]\")) {\n            host = host.substring(1, host.length() - 1);\n        }\n        try {\n            for (InetAddress addr : InetAddress.getAllByName(host)) {\n                if (addr.isLoopbackAddress() || addr.isLinkLocalAddress()) {\n                    throw new JeecgBootException(\"非法URL：禁止访问本机或链路本地地址 \" + addr.getHostAddress());\n                }","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/jeecgboot/JeecgBoot/blob/96fb33f5ec68516da0b0147da06b2eb0419e063a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/filter/SsrfFileTypeFilter.java#L312-L348","documentation":"Thrown by checkSsrfHttpUrl when new URI(fileUrl) raises URISyntaxException — the URL string is syntactically invalid per RFC 3986. This guards against malformed URLs that could bypass downstream host/scheme checks or cause unpredictable behavior in URLConnection.","triggerScenarios":"Passing a URL with illegal characters (e.g., spaces, unencoded brackets), truncated URLs, URLs with mismatched scheme separators (e.g., 'http//example.com'), or strings that look like file paths rather than URLs.","commonSituations":"User pastes a partial URL missing the '//' after scheme; front-end sends a relative path like '/files/image.png' instead of a full absolute URL; copy-paste introduces invisible/zero-width characters; URL contains unencoded Chinese characters or spaces.","solutions":["Trim and validate the URL on the client side before submission.","If relative paths are expected, prepend the configured base URL (e.g., MinIO/OSS endpoint) before calling checkSsrfHttpUrl.","URL-encode any user-supplied path segments before constructing the full URL.","Catch JeecgBootException at the controller layer and return a user-friendly Result.error()."],"exampleFix":"// before\nString fileUrl = userInput; // e.g. \"http//broken\"\nSsrfFileTypeFilter.checkSsrfHttpUrl(fileUrl);\n\n// after\nString fileUrl = userInput.trim();\nif (!fileUrl.startsWith(\"http://\") && !fileUrl.startsWith(\"https://\")) {\n    fileUrl = serverBaseUrl + (fileUrl.startsWith(\"/\") ? fileUrl : \"/\" + fileUrl);\n}\nSsrfFileTypeFilter.checkSsrfHttpUrl(fileUrl);","handlingStrategy":"validation","validationCode":"try {\n    new URI(fileUrl);\n} catch (URISyntaxException e) {\n    return Result.error(\"URL格式不正确: \" + fileUrl);\n}","typeGuard":null,"tryCatchPattern":"try {\n    SsrfFileTypeFilter.checkSsrfHttpUrl(fileUrl);\n} catch (JeecgBootException e) {\n    log.warn(\"Invalid URL format: {}\", fileUrl);\n    return Result.error(e.getMessage());\n}","preventionTips":["URL-encode user-supplied path segments before constructing URLs.","Prepend a base URL for relative paths before validation.","Validate URL structure on the front-end before submission."],"tags":["ssrf","validation","url","uri","security"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}