Class SsrfUrlValidator


  • public final class SsrfUrlValidator
    extends Object
    Validates that a (client-supplied) URL is safe for the server to fetch, to prevent server-side request forgery (SSRF).

    A URL is considered safe only when it uses the http or https scheme (which rules out file://, ftp://, gopher:// and similar variants) and none of the host's resolved addresses point at a blocked target. Blocked targets are:

    • loopback (127.0.0.0/8, ::1), wildcard (0.0.0.0, ::), link-local (incl. cloud metadata 169.254.0.0/16 and fe80::/10), private/site-local (10/8, 172.16/12, 192.168/16) and multicast addresses, as reported by InetAddress;
    • IPv6 unique-local addresses (fc00::/7), not reported by isSiteLocalAddress();
    • IPv4 special-purpose ranges that InetAddress.is*Address() does not flag: 0.0.0.0/8 (RFC 1122), 100.64.0.0/10 shared address space (RFC 6598, incl. the 100.100.100.200 cloud metadata endpoint), 192.0.0.0/24 (RFC 6890), 192.88.99.0/24 (RFC 7526), 198.18.0.0/15 (RFC 2544) and 240.0.0.0/4 reserved incl. the 255.255.255.255 broadcast;
    • the whole NAT64 local-use prefix 64:ff9b:1::/48 (RFC 8215). Unlike the Well-Known Prefix, which RFC 6052 §3.1 forbids using for non-global IPv4, this prefix exists precisely to translate non-global IPv4, and the operator picks the sub-prefix inside the /48 — so the embedding offset is not knowable from the literal. It is translation-only space with no legitimate fetch target, so all of it is blocked rather than only one sub-prefix;
    • the IPv4 address embedded in an IPv6 transition host literal — NAT64 Well-Known Prefix (64:ff9b::/96, RFC 6052 §2.1), 6to4 (2002::/16), Teredo (2001:0000::/32), ISATAP (interface identifier 0000:5efe / 0200:5efe, RFC 5214) and IPv4-mapped/compatible (::ffff:0:0/96, ::/96) — which is extracted and re-checked against every rule above, so an internal target cannot be smuggled in through a transition address. A literal may embed more than one candidate (e.g. a 6to4 prefix with an ISATAP interface identifier); every candidate is checked.
    • the IPv4 address embedded under an operator-configured NAT64 Network-Specific Prefix, see NAT64_PREFIXES_PROPERTY.

    NAT64 Network-Specific Prefixes (RFC 6052 §2.2) are chosen by the operator out of the operator's own address space and are bit-for-bit indistinguishable from an ordinary global address, so they cannot be recognised from the literal alone. Deployments that run a NAT64 with an NSP must declare it through NAT64_PREFIXES_PROPERTY; nothing is inferred.

    Note that the check is applied to the addresses the host resolves to at validation time. A name that resolves to a different address when the URL is later fetched (DNS rebinding) is out of scope here and has to be handled by the fetching code.

    Apart from NAT64_PREFIXES_PROPERTY, which can only ever add blocked ranges, this class carries no configuration of its own: callers that need a runtime "allow any URL" escape hatch read their own system property and short-circuit before calling isSafeRemoteUrl(String).

    • Field Detail

      • NAT64_PREFIXES_PROPERTY

        public static final String NAT64_PREFIXES_PROPERTY
        Comma-separated list of NAT64 Network-Specific Prefixes (RFC 6052 §2.2) in use by this deployment, each written as <ipv6-prefix>/<length> with a length of 32, 40, 48, 56, 64 or 96 bits — for example org.openidentityplatform.ssrf.nat64-prefixes=2001:db8:122:344::/64,2001:db8:1::/48.

        The IPv4 address embedded under each declared prefix is extracted per RFC 6052 §2.2 and re-checked, which closes the NAT64 bypass for deployments that do not use the Well-Known Prefix. An NSP cannot be inferred from an address literal, so without this property such prefixes are simply not recognised — the property can only ever block more, never less.

        Unparsable entries are skipped with a warning in the amSSRF debug log; the remaining entries and all built-in rules still apply.

        See Also:
        Constant Field Values
    • Method Detail

      • isSafeRemoteUrl

        public static boolean isSafeRemoteUrl​(String url)
        Equivalent to isSafeRemoteUrl(url, false): both http and https URLs are accepted.
        Parameters:
        url - the URL to check.
        Returns:
        true if the URL is safe for the server to fetch, false otherwise.
      • isSafeRemoteUrl

        public static boolean isSafeRemoteUrl​(String url,
                                              boolean requireHttps)
        Parameters:
        url - the URL to check.
        requireHttps - when true only the https scheme is accepted; when false both http and https are accepted.
        Returns:
        true if the URL is safe for the server to fetch, false otherwise.