{"record":{"id":"953925551437db79","repo":"apache/shenyu","slug":"invalid-url-format","errorCode":null,"errorMessage":"Invalid URL format","messagePattern":"Invalid URL format","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"shenyu-admin/src/main/java/org/apache/shenyu/admin/utils/UrlSecurityUtils.java","lineNumber":57,"sourceCode":"     * Private constructor to prevent instantiation.\n     */\n    private UrlSecurityUtils() {\n    }\n\n    /**\n     * Validate URL to prevent SSRF attacks.\n     *\n     * @param url the URL to validate\n     * @throws IllegalArgumentException if the URL is not safe for external requests\n     */\n    public static void validateUrlForSSRF(final String url) {\n        if (Objects.isNull(url) || url.trim().isEmpty()) {\n            throw new IllegalArgumentException(\"URL cannot be empty\");\n        }\n\n        HttpUrl parsedUrl = HttpUrl.parse(url);\n        if (Objects.isNull(parsedUrl)) {\n            throw new IllegalArgumentException(\"Invalid URL format\");\n        }\n\n        String protocol = parsedUrl.scheme();\n\n        // Only allow HTTP and HTTPS protocols\n        if (!HTTP_PROTOCOL.equals(protocol) && !HTTPS_PROTOCOL.equals(protocol)) {\n            throw new IllegalArgumentException(\"Only HTTP and HTTPS protocols are allowed\");\n        }\n\n        // Validate host for SSRF protection using the same URL parser as request execution.\n        validateHostForSSRF(parsedUrl.host(), parsedUrl.port());\n    }\n\n    /**\n     * Validate host to prevent SSRF attacks.\n     *\n     * @param host the host to validate\n     * @param port the port to validate","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-admin/src/main/java/org/apache/shenyu/admin/utils/UrlSecurityUtils.java#L39-L75","documentation":"validateUrlForSSRF parses the URL with OkHttp's HttpUrl.parse; if parsing fails (the string is not a well-formed absolute HTTP URL) it throws IllegalArgumentException \"Invalid URL format\". This prevents malformed strings from ever reaching request execution.","triggerScenarios":"Passing strings without a scheme ('example.com/api'), with unsupported schemes relative to OkHttp's parser, containing invalid characters/spaces, or garbage/placeholder values ('${HOST}', 'localhost:99999').","commonSituations":"Users entering host names without http(s):// in admin forms; config values with unresolved env placeholders; trailing whitespace or hidden characters pasted from docs.","solutions":["Enter the URL with an explicit scheme: http:// or https:// plus valid host and path.","Trim whitespace and remove quotes/placeholders from the configured value.","Pre-validate in the UI with a URL parser before saving the config.","Catch IllegalArgumentException and show which field contains the malformed URL."],"exampleFix":"// before\nvalidateUrlForSSRF(\"backend.example.com:8080/api\");\n// after\nvalidateUrlForSSRF(\"http://backend.example.com:8080/api\");","handlingStrategy":"validation","validationCode":"HttpUrl parsed = HttpUrl.parse(url);\nif (parsed == null) {\n    throw new IllegalArgumentException(\"Not a valid absolute http(s) URL: \" + url);\n}\nif (!url.trim().equals(url)) throw new IllegalArgumentException(\"URL has surrounding whitespace\");","typeGuard":"boolean isParsableUrl(String s) { return s != null && HttpUrl.parse(s.trim()) != null; }","tryCatchPattern":"try {\n    UrlSecurityUtils.validateUrlForSSRF(url);\n} catch (IllegalArgumentException e) {\n    return ResponseEntity.badRequest().body(\"Invalid URL: use a full http(s):// URL\");\n}","preventionTips":["Always include the scheme (http:// or https://) in configured URLs.","Trim whitespace and strip quotes when accepting pasted URLs.","Validate with HttpUrl.parse (same parser the gateway uses) before saving.","Reject placeholder values like ${HOST} at config-load time."],"tags":["ssrf","url","validation","security"],"backgroundTag":"invalid-url-format","analyzedSha":"567142e07261b3e615ae8850b30f4421f455cc5d","analyzedAt":"2026-09-12T10:08:21.293Z","contentChangedAt":"2026-09-12T10:08:21.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}