apache/shenyu · error · IllegalArgumentException

Resolved IP address is private: " + address.getHostAddress()

Error message

Resolved IP address is private: " + address.getHostAddress()

What it means

validateHostForSSRF performs a second pass over each DNS-resolved address using the custom isPrivateIPAddress() range check (beyond InetAddress's built-in flags). If any resolved IP falls in a configured private range, it throws this IllegalArgumentException. It exists to catch private ranges the JDK flags do not cover.

Solutions

  1. Use a hostname that resolves to a public address.
  2. If your environment legitimately uses these ranges, route through a public proxy endpoint instead.
  3. For tests, extend the private-range list only in test scopes; keep production ranges strict.

Example fix

// before
UrlSecurityUtils.validateUrlForSSRF("http://svc.internal:8080"); // resolves to 100.64.1.5
// after
UrlSecurityUtils.validateUrlForSSRF("https://svc.example.com");
Defensive patterns

Strategy: try-catch

Validate before calling

InetAddress[] addrs = InetAddress.getAllByName(host);
for (InetAddress a : addrs) {
    if (isPrivateIPAddress(a.getHostAddress())) {
        throw new IllegalArgumentException("resolves to private range: " + a.getHostAddress());
    }
}

Type guard

boolean allResolvedIpsPublic(String host) throws UnknownHostException {
    return Arrays.stream(InetAddress.getAllByName(host))
        .allMatch(a -> !isPrivateIPAddress(a.getHostAddress()));
}

Try / catch

try {
    UrlSecurityUtils.validateUrlForSSRF(url);
} catch (IllegalArgumentException e) {
    log.warn("Resolved IP in private range: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Validating a hostname whose DNS resolves to an IP matched by isPrivateIPAddress() (e.g. CGNAT 100.64.x, other internal CIDR ranges), even when InetAddress.isSiteLocalAddress() returns false.

Common situations: Deployments behind NAT64/CGNAT or corporate ranges (100.64.0.0/10, 198.18.0.0/15) where the service hostname legitimately resolves to such addresses.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12). Data as JSON: /api/errors/ecf14e21ece87736. Report an issue: GitHub.

Appendix: source

Thrown at shenyu-admin/src/main/java/org/apache/shenyu/admin/utils/UrlSecurityUtils.java:111

        }

        // Check for sensitive ports
        if (isSensitivePort(port)) {
            throw new IllegalArgumentException("Access to sensitive ports is not allowed");
        }

        // Additional validation for DNS resolution
        try {
            InetAddress[] addresses = InetAddress.getAllByName(normalizedHost);
            for (InetAddress address : addresses) {
                if (address.isLoopbackAddress() || address.isLinkLocalAddress()
                        || address.isSiteLocalAddress() || address.isAnyLocalAddress()) {
                    throw new IllegalArgumentException("Resolved IP address is not allowed: " + address.getHostAddress());
                }

                // Check resolved IP against private ranges
                if (isPrivateIPAddress(address.getHostAddress())) {
                    throw new IllegalArgumentException("Resolved IP address is private: " + address.getHostAddress());
                }
            }
        } catch (UnknownHostException e) {
            throw new IllegalArgumentException("Cannot resolve host: " + host);
        }
    }

    /**
     * Check if the host is localhost or localhost variations.
     *
     * @param host the host to check
     * @return true if the host is localhost
     */
    private static boolean isLocalhost(final String host) {
        Set<String> localhostVariations = new HashSet<>(Arrays.asList(
                "localhost", "127.0.0.1", "::1", "0.0.0.0", "0000:0000:0000:0000:0000:0000:0000:0001"
        ));
        return localhostVariations.contains(host);

View on GitHub (pinned to 567142e072)