apache/shenyu · error · IllegalArgumentException

Resolved IP address is not allowed: " +…

Error message

Resolved IP address is not allowed: " + address.getHostAddress()

What it means

After resolving the host via InetAddress.getAllByName, validateHostForSSRF throws this IllegalArgumentException if any resolved address is loopback, link-local, site-local, or the wildcard/any-local address. This closes the DNS-rebinding-style gap where a benign hostname resolves to a dangerous internal IP.

Solutions

  1. Give the target host a public DNS record that resolves only to non-private, non-loopback addresses.
  2. Clean up /etc/hosts or DNS entries that map the hostname to 127.0.0.1 or link-local addresses.
  3. If the service must stay internal, call it directly rather than through the SSRF-validated path.

Example fix

// before (hosts file: service.local -> 127.0.0.1)
UrlSecurityUtils.validateUrlForSSRF("http://service.local/api");
// after (service.local -> public IP)
UrlSecurityUtils.validateUrlForSSRF("https://service.example.com/api");
Defensive patterns

Strategy: try-catch

Validate before calling

InetAddress[] addrs = InetAddress.getAllByName(host);
for (InetAddress a : addrs) {
    if (a.isLoopbackAddress() || a.isLinkLocalAddress() || a.isSiteLocalAddress() || a.isAnyLocalAddress()) {
        throw new IllegalArgumentException("resolves to restricted IP: " + a.getHostAddress());
    }
}

Type guard

boolean resolvesPublicly(String host) throws UnknownHostException {
    return Arrays.stream(InetAddress.getAllByName(host))
        .noneMatch(a -> a.isLoopbackAddress() || a.isSiteLocalAddress() || a.isLinkLocalAddress());
}

Try / catch

try {
    UrlSecurityUtils.validateUrlForSSRF(url);
} catch (IllegalArgumentException e) {
    log.warn("Host resolves to disallowed address: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Validating a hostname whose DNS records include 127.0.0.0/8, 169.254.x, 10.x/172.16-31.x/192.168.x, or 0.0.0.0 — e.g. http://localhost.example.com or a hostname pointing at 127.0.0.1.

Common situations: DNS entries (or /etc/hosts overrides) mapping service names to loopback or private addresses; testing in containers where the target resolves to a link-local or loopback address.

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/fae1cfe6fb305eaf. Report an issue: GitHub.

Appendix: source

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

        }

        // Check for private IP addresses
        if (isPrivateOrInternalIP(normalizedHost)) {
            throw new IllegalArgumentException("Access to private or internal IP addresses is not allowed");
        }

        // 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
     */

View on GitHub (pinned to 567142e072)