{"record":{"id":"7716c14ee16b862d","repo":"spring-projects/spring-ai","slug":"failed-to-resolve-host","errorCode":null,"errorMessage":"Failed to resolve host: ","messagePattern":"Failed to resolve host: ","errorType":"exception","errorClass":"java.lang.SecurityException","httpStatus":null,"severity":"error","filePath":"models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/api/URLValidator.java","lineNumber":143,"sourceCode":"\t * {@link SecurityException} if any resolve to a loopback, link-local, site-local, or\n\t * wildcard address. Protects against SSRF via internal network access (including IPv6\n\t * equivalents) and limits exposure from DNS rebinding by checking all returned\n\t * addresses.\n\t * @param host the hostname to check\n\t * @throws SecurityException if the host resolves to a blocked internal address or\n\t * cannot be resolved\n\t */\n\tpublic static void assertNoInternalAddress(String host) {\n\t\ttry {\n\t\t\tfor (InetAddress address : InetAddress.getAllByName(host)) {\n\t\t\t\tif (isBlockedAddress(address)) {\n\t\t\t\t\tthrow new SecurityException(\"URL host '\" + host + \"' resolves to a blocked internal address: \"\n\t\t\t\t\t\t\t+ address.getHostAddress());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcatch (UnknownHostException e) {\n\t\t\tthrow new SecurityException(\"Failed to resolve host: \" + host, e);\n\t\t}\n\t}\n\n\t/**\n\t * Returns {@code true} if the given address is a loopback, link-local, site-local, or\n\t * wildcard address. Covers both IPv4 and IPv6 private/internal ranges.\n\t * @param address the address to test\n\t * @return {@code true} if the address should be blocked\n\t */\n\tpublic static boolean isBlockedAddress(InetAddress address) {\n\t\treturn address.isLoopbackAddress() || address.isLinkLocalAddress() || address.isSiteLocalAddress()\n\t\t\t\t|| address.isAnyLocalAddress();\n\t}\n\n\t/**\n\t * Attempts to fix common URL issues Adds protocol if missing, removes extra spaces\n\t */\n\tpublic static @Nullable String normalizeURL(@Nullable String urlString) {","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/models/spring-ai-bedrock-converse/src/main/java/org/springframework/ai/bedrock/converse/api/URLValidator.java#L125-L161","documentation":"When URLValidator.assertNoInternalAddress cannot resolve the host at all, InetAddress.getAllByName throws UnknownHostException, which is translated into this SecurityException (with the original exception attached) so it flows through Spring RestClient as a RuntimeException instead of being wrapped in ResourceAccessException. It signals the strict URL check could not complete because DNS resolution failed.","triggerScenarios":"isValidURLStrict → assertNoInternalAddress with a hostname that DNS cannot resolve: typo'd domains, unregistered hosts, names only resolvable on an internal DNS server the runtime cannot reach, or environments with broken/no DNS.","commonSituations":"Typo in the media URL host (e.g. .con instead of .com); using a corporate-internal hostname from a network without the internal DNS; running in a container/pod with misconfigured resolv.conf or blocked DNS egress; transient DNS resolver outages.","solutions":["Verify the hostname is spelled correctly and is publicly resolvable (dig/nslookup/ping it from the runtime environment).","Fix DNS in the runtime environment (resolv.conf, CoreDNS, VPC DNS settings) if legitimate public hosts fail to resolve.","Replace internal-only hostnames with public CDN/S3 endpoints, or fetch the media yourself and pass bytes inline.","Catch SecurityException and surface a 'could not resolve media host' validation error to the caller; optionally retry on transient DNS failures."],"exampleFix":"// before\nMedia media = new Media(MimeTypeUtils.IMAGE_JPEG, new URL(\"https://medai.example.com/cat.jpg\")); // typo: medai\n// after\nMedia media = new Media(MimeTypeUtils.IMAGE_JPEG, new URL(\"https://media.example.com/cat.jpg\"));","handlingStrategy":"try-catch","validationCode":"// Java: attempt resolution yourself first and fail fast with a clear message\ntry {\n    InetAddress.getAllByName(mediaUrl.getHost());\n} catch (UnknownHostException e) {\n    throw new IllegalArgumentException(\"Media URL host cannot be resolved: \" + mediaUrl.getHost(), e);\n}","typeGuard":null,"tryCatchPattern":"try {\n    model.call(prompt);\n} catch (SecurityException e) {\n    if (e.getMessage().startsWith(\"Failed to resolve host\")) {\n        // report DNS failure to the user; optionally retry once for transient DNS issues\n    } else { throw e; }\n}","preventionTips":["Verify hostnames resolve (dig/nslookup) from the same environment that runs the model call.","Check DNS configuration in containers/Kubernetes (resolv.conf, CoreDNS) before deploying.","Validate URL syntax and hostname format at your API boundary.","Apply a small retry with backoff for transient DNS failures, but never for blocked/internal-address rejections."],"tags":["security","dns","unknown-host","url-validation","bedrock"],"backgroundTag":"invalid-url","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}