{"record":{"id":"eae5e45cc015d52c","repo":"conductor-oss/conductor","slug":"access-denied-link-local-address-range-is-blocked","errorCode":null,"errorMessage":"Access denied: link-local address range is blocked (host resolves to {address})","messagePattern":"Access denied: link-local address range is blocked \\(host resolves to (.+?)\\)","errorType":"validation","errorClass":"DocumentAccessDeniedException","httpStatus":null,"severity":"critical","filePath":"ai/src/main/java/org/conductoross/conductor/ai/document/DocumentAccessPolicy.java","lineNumber":358,"sourceCode":"                        \"Access denied: host '\" + host + \"' is blocked\");\n            }\n        }\n\n        // Resolve hostname to IP and check for link-local / metadata ranges.\n        // This catches obfuscated IPs (hex, octal, decimal encoding) and DNS\n        // rebinding because InetAddress.getByName normalizes all representations.\n        checkResolvedAddress(host);\n    }\n\n    /**\n     * Resolves the host to an IP address and blocks link-local (169.254.0.0/16) and other dangerous\n     * ranges that are commonly used for SSRF against cloud metadata services.\n     */\n    private void checkResolvedAddress(String host) {\n        try {\n            InetAddress addr = InetAddress.getByName(host);\n            if (addr.isLinkLocalAddress()) {\n                throw new DocumentAccessDeniedException(\n                        \"Access denied: link-local address range is blocked (host resolves to \"\n                                + addr.getHostAddress()\n                                + \")\");\n            }\n            if (addr.isLoopbackAddress()) {\n                throw new DocumentAccessDeniedException(\n                        \"Access denied: loopback address is blocked (host resolves to \"\n                                + addr.getHostAddress()\n                                + \")\");\n            }\n        } catch (DocumentAccessDeniedException e) {\n            throw e;\n        } catch (Exception e) {\n            // DNS resolution failure — allow the request to proceed and fail naturally\n            log.debug(\n                    \"Could not resolve host '{}' for access policy check: {}\",\n                    host,\n                    e.getMessage());","sourceCodeStart":340,"sourceCodeEnd":376,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/ai/src/main/java/org/conductoross/conductor/ai/document/DocumentAccessPolicy.java#L340-L376","documentation":"Thrown by DocumentAccessPolicy.checkResolvedAddress after DNS resolution: the host resolved to an InetAddress whose isLinkLocalAddress() is true (169.254.0.0/16 and IPv6 link-local). This catches obfuscated metadata-IP access (decimal/hex/octal encodings, DNS rebinding) that would slip past the string blocklist, because InetAddress.getByName normalizes all representations before the check. DocumentAccessDeniedException (SecurityException); the resolved address is included in the message.","triggerScenarios":"A loader is pointed at a hostname or non-canonical IP that resolves into the link-local range, e.g. http://0xa9fe1694/ (hex for 169.254.22.148), a DNS rebinding domain that flips to 169.254.x.x, or fe80::/ IPv6.","commonSituations":"SSRF/prompt-injection attempts using encoded IP forms; a legitimately misconfigured internal service that advertises a link-local address; IPv6 link-local endpoints.","solutions":["Use the real external hostname/IP for the resource you need — link-local addresses are never valid service endpoints.","If this is an SSRF attempt, treat the input as hostile and reject the whole request upstream.","For a misconfigured service, fix its DNS/DHCP so it advertises a routable address."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Resolve and reject link-local before the loader call\njava.net.InetAddress a = java.net.InetAddress.getByName(host);\nif (a.isLinkLocalAddress()) {\n    throw new SecurityException(\"Refusing link-local host: \" + host + \" -> \" + a.getHostAddress());\n}","typeGuard":null,"tryCatchPattern":"try {\n    loader.download(url);\n} catch (SecurityException e) {\n    // link-local (169.254/16) is never a valid service endpoint — do not bypass\n    throw new SecurityException(\"Blocked link-local resolution for: \" + url, e);\n}","preventionTips":["Use routable hostnames/IPs for all external resources.","Treat encoded/obfuscated IPs in input as hostile.","Pin services to stable public DNS, not link-local addresses."],"tags":["security","ssrf","access-control","document-loader","dns","cloud-metadata"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}