{"record":{"id":"7d066c652bab413f","repo":"apache/shenyu","slug":"access-to-private-or-internal-ip-addresses-is-not-allowed","errorCode":null,"errorMessage":"Access to private or internal IP addresses is not allowed","messagePattern":"Access to private or internal IP addresses is not allowed","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"shenyu-admin/src/main/java/org/apache/shenyu/admin/utils/UrlSecurityUtils.java","lineNumber":92,"sourceCode":"     * @param host the host to validate\n     * @param port the port to validate\n     * @throws IllegalArgumentException if the host is not allowed\n     */\n    public static void validateHostForSSRF(final String host, final int port) {\n        if (Objects.isNull(host) || host.trim().isEmpty()) {\n            throw new IllegalArgumentException(\"Host cannot be empty\");\n        }\n\n        String normalizedHost = host.toLowerCase().trim();\n\n        // Check for localhost variations\n        if (isLocalhost(normalizedHost)) {\n            throw new IllegalArgumentException(\"Access to localhost is not allowed\");\n        }\n\n        // Check for private IP addresses\n        if (isPrivateOrInternalIP(normalizedHost)) {\n            throw new IllegalArgumentException(\"Access to private or internal IP addresses is not allowed\");\n        }\n\n        // Check for sensitive ports\n        if (isSensitivePort(port)) {\n            throw new IllegalArgumentException(\"Access to sensitive ports is not allowed\");\n        }\n\n        // Additional validation for DNS resolution\n        try {\n            InetAddress[] addresses = InetAddress.getAllByName(normalizedHost);\n            for (InetAddress address : addresses) {\n                if (address.isLoopbackAddress() || address.isLinkLocalAddress()\n                        || address.isSiteLocalAddress() || address.isAnyLocalAddress()) {\n                    throw new IllegalArgumentException(\"Resolved IP address is not allowed: \" + address.getHostAddress());\n                }\n\n                // Check resolved IP against private ranges\n                if (isPrivateIPAddress(address.getHostAddress())) {","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-admin/src/main/java/org/apache/shenyu/admin/utils/UrlSecurityUtils.java#L74-L110","documentation":"UrlSecurityUtils.validateHostForSSRF throws this IllegalArgumentException when the requested host normalizes to a private or internal IP address (e.g. 10.x, 172.16-31.x, 192.168.x). ShenYu admin validates outbound URLs to prevent SSRF attacks where a caller could make the server reach internal infrastructure. The check runs before any HTTP request is issued.","triggerScenarios":"Calling validateUrlForSSRF/validateHostForSSRF with a URL whose host is a literal private IP (http://192.168.1.10:8080/...) or a hostname that isPrivateOrInternalIP() classifies as internal.","commonSituations":"Pointing health-check, divide/upstream, or config-fetch URLs at internal services during local development or in an on-prem deployment where backends genuinely live on private networks.","solutions":["Change the URL to use a public, routable hostname/IP.","If the target is intentionally internal, access it through an approved proxy or public endpoint instead of bypassing the check.","Do not weaken isPrivateOrInternalIP for production; if testing, use a mock server on a non-private address or unit-test the validator directly."],"exampleFix":"// before\nString url = \"http://192.168.1.10:8080/actuator/health\";\nUrlSecurityUtils.validateUrlForSSRF(url);\n// after\nString url = \"https://api.example.com/actuator/health\";\nUrlSecurityUtils.validateUrlForSSRF(url);","handlingStrategy":"validation","validationCode":"boolean isPrivateLiteral(String host) {\n    return host.matches(\"^(10\\\\.|172\\\\.(1[6-9]|2\\\\d|3[01])\\\\.|192\\\\.168\\\\.|127\\\\.).*\");\n}\nif (isPrivateLiteral(host)) { throw new IllegalArgumentException(\"private host: \" + host); }","typeGuard":"boolean isPublicHost(String host) {\n    return !(isLocalhost(host) || isPrivateOrInternalIP(host));\n}","tryCatchPattern":"try {\n    UrlSecurityUtils.validateUrlForSSRF(url);\n} catch (IllegalArgumentException e) {\n    log.warn(\"URL rejected by SSRF guard: {}\", e.getMessage());\n}","preventionTips":["Use public hostnames for all cross-service URLs configured in admin.","Never hardcode 192.168.x/10.x addresses into dashboard-configured URLs.","Add a pre-save check in your own tooling that mirrors the SSRF rules."],"tags":["ssrf","security","url-validation","network"],"backgroundTag":"invalid-url","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"}