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
- Use a public-facing URL whose host resolves only to public IP addresses.
- For internal content, fetch it yourself and pass the media bytes inline to Media rather than a URL.
- Inspect resolution with nslookup/dig and fix unintended private DNS records or /etc/hosts entries.
- 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
- Call URLValidator.assertNoInternalAddress/isValidURLStrict on user-supplied URLs at ingestion time, not at model-call time.
- Whitelist approved media hosts rather than accepting arbitrary URLs.
- Never whitelist localhost or private-range hosts in your URL allowlist.
- Log rejected hosts with resolved addresses to spot SSRF probing early.
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
- Host '' resolves to a blocked internal address:
- Failed to resolve host:
- URL is not valid under strict validation rules:
- Host '' is not in the allowed hosts list. Configure MediaFet
- Connection to blocked internal address rejected for host ''
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/cd769cc9f09c2570.
Report an issue: GitHub.