spring-projects/spring-ai · error · java.lang.SecurityException

URL host '' resolves to a blocked internal address:

Error message

URL host '' resolves to a blocked internal address: 

What it means

URLValidator.assertNoInternalAddress resolves the given host with InetAddress.getAllByName and throws this SecurityException if any resolved IP is a blocked internal address (loopback, link-local, site-local/private, wildcard). It is part of the strict URL validation (isValidURLStrict) performed on user-supplied media URLs before fetching, to prevent SSRF against internal networks.

Source

Thrown at models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/api/URLValidator.java:137

			return false;
		}
	}

	/**
	 * Resolves all IP addresses for the given hostname and throws
	 * {@link SecurityException} if any resolve to a loopback, link-local, site-local, or
	 * wildcard address. Protects against SSRF via internal network access (including IPv6
	 * equivalents) and limits exposure from DNS rebinding by checking all returned
	 * addresses.
	 * @param host the hostname to check
	 * @throws SecurityException if the host resolves to a blocked internal address or
	 * cannot be resolved
	 */
	public static void assertNoInternalAddress(String host) {
		try {
			for (InetAddress address : InetAddress.getAllByName(host)) {
				if (isBlockedAddress(address)) {
					throw new SecurityException("URL host '" + host + "' resolves to a blocked internal address: "
							+ address.getHostAddress());
				}
			}
		}
		catch (UnknownHostException e) {
			throw new SecurityException("Failed to resolve host: " + host, e);
		}
	}

	/**
	 * Returns {@code true} if the given address is a loopback, link-local, site-local, or
	 * wildcard address. Covers both IPv4 and IPv6 private/internal ranges.
	 * @param address the address to test
	 * @return {@code true} if the address should be blocked
	 */
	public static boolean isBlockedAddress(InetAddress address) {
		return address.isLoopbackAddress() || address.isLinkLocalAddress() || address.isSiteLocalAddress()
				|| address.isAnyLocalAddress();

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Use a public-facing URL whose host resolves only to public IP addresses.
  2. For internal content, fetch it yourself and pass the media bytes inline to Media rather than a URL.
  3. Inspect resolution with nslookup/dig and fix unintended private DNS records or /etc/hosts entries.
  4. Catch SecurityException in your input-validation layer and reject the URL with a user-facing message before invoking the model.

Example fix

// before
URLValidator.assertNoInternalAddress("169.254.169.254"); // throws
// after
URLValidator.assertNoInternalAddress("cdn.example.com"); // public resolution passes
Defensive patterns

Strategy: validation

Validate before calling

// Java: run the same strict validation before invoking the model
try {
    org.springframework.ai.bedrock.converse.api.URLValidator.assertNoInternalAddress(new URI(mediaUrl).getHost());
} catch (SecurityException e) {
    throw new IllegalArgumentException("Rejecting media URL: " + e.getMessage(), e);
}

Try / catch

try {
    model.call(prompt);
} catch (SecurityException e) {
    if (e.getMessage().startsWith("URL host")) {
        // return 400-style validation error to the caller; no retry
    } else { throw e; }
}

Prevention

When it happens

Trigger: Passing a URL to strict validation (isValidURLStrict) whose host's DNS resolution includes any internal IP — e.g. localhost names, 127.0.0.1, 10.x/172.16.x/192.168.x ranges, 169.254.169.254 metadata IP, or IPv6 loopback/link-local.

Common situations: Developer URLs like http://localhost:8080/media.png used in integration tests; internal-only artifact hosts; DNS in containerized/Kubernetes environments where service names resolve to cluster-internal IPs; SSRF probes targeting cloud metadata endpoints.

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 spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/cd769cc9f09c2570. Report an issue: GitHub.