conductor-oss/conductor · critical · DocumentAccessDeniedException
Access denied: host '{host}' is blocked
Error message
Access denied: host '{host}' is blocked What it means
Thrown by DocumentAccessPolicy.checkBlockedHosts when the host of an HTTP(S) location exactly matches (case-insensitive) one of the built-in DEFAULT_BLOCKED_HOSTS — cloud metadata endpoints and in-cluster APIs: 169.254.169.254, 169.254.170.2, metadata.google.internal, 100.100.100.200, kubernetes.default(.svc/.svc.cluster.local), fd00:ec2::254. This is the primary SSRF guard against metadata-service theft. DocumentAccessDeniedException (SecurityException).
Source
Thrown at ai/src/main/java/org/conductoross/conductor/ai/document/DocumentAccessPolicy.java:333
for (String blocked : blockedFileNames) {
if (lowerFileName.equals(blocked.toLowerCase())) {
throw new DocumentAccessDeniedException(
"Access denied: file name '" + fileName + "' is blocked");
}
}
}
private void checkBlockedHosts(String location) {
String host = extractHost(location);
if (host == null || host.isEmpty()) {
return;
}
String lowerHost = host.toLowerCase();
// Check against explicit blocklist
for (String blocked : DEFAULT_BLOCKED_HOSTS) {
if (lowerHost.equals(blocked.toLowerCase())) {
throw new DocumentAccessDeniedException(
"Access denied: host '" + host + "' is blocked");
}
}
for (String blocked : blockedHosts) {
if (lowerHost.equals(blocked.toLowerCase())) {
throw new DocumentAccessDeniedException(
"Access denied: host '" + host + "' is blocked");
}
}
// Resolve hostname to IP and check for link-local / metadata ranges.
// This catches obfuscated IPs (hex, octal, decimal encoding) and DNS
// rebinding because InetAddress.getByName normalizes all representations.
checkResolvedAddress(host);
}
/**
* Resolves the host to an IP address and blocks link-local (169.254.0.0/16) and other dangerousView on GitHub (pinned to cf7c3e4a8a)
Solutions
- Point the loader at the legitimate external URL instead of a metadata/Kubernetes endpoint.
- Treat any such URL in your data as an injection attempt and reject it upstream.
- Never feed untrusted/LLM-generated URLs directly to the document loader.
Example fix
// before
loader.download("http://169.254.169.254/latest/meta-data/iam/...")
// after — use the real external resource
loader.download("https://api.example.com/v1/data") Defensive patterns
Strategy: validation
Validate before calling
// Reject metadata/in-cluster endpoints before any HTTP loader call
private static final Set<String> META = Set.of(
"169.254.169.254","169.254.170.2","metadata.google.internal",
"100.100.100.200","kubernetes.default");
String host = java.net.URI.create(url).getHost();
if (host != null && META.contains(host.toLowerCase())) {
throw new SecurityException("Refusing metadata endpoint: " + url);
} Try / catch
try {
loader.download(url);
} catch (SecurityException e) {
// built-in host denylist — never bypass; treat as SSRF/injection
throw new SecurityException("Blocked host in URL: " + url, e);
} Prevention
- Never feed untrusted/LLM-generated URLs to the document loader.
- Treat any metadata/Kubernetes-API URL in input data as an injection attempt.
- Allow-list external hosts upstream rather than relying solely on the blocklist.
When it happens
Trigger: An HTTP document loader (HttpDocumentLoader) is given a URL whose host is a metadata endpoint or the in-cluster Kubernetes API — e.g. http://169.254.169.254/latest/meta-data/ or http://kubernetes.default/api.
Common situations: Prompt injection or a misconfigured URL template points a loader at a metadata service to steal cloud tokens; a workflow tries to call the in-cluster Kubernetes API from a document task.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Access denied: path matches blocked prefix '{prefix}'
- Access denied: link-local address range is blocked (host res
- Access denied: file name '{fileName}' is blocked
- Access denied: loopback address is blocked (host resolves to
- agentUrl resolves to a cloud metadata address — SSRF blocked
AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14).
Data as JSON: /api/errors/37e76f46f08cfe36.
Report an issue: GitHub.