{"record":{"id":"ddea2aef71ee6dd3","repo":"conductor-oss/conductor","slug":"access-denied-path-matches-blocked-prefix-prefi","errorCode":null,"errorMessage":"Access denied: path matches blocked prefix '{prefix}'","messagePattern":"Access denied: path matches blocked prefix '(.+?)'","errorType":"validation","errorClass":"DocumentAccessDeniedException","httpStatus":null,"severity":"critical","filePath":"ai/src/main/java/org/conductoross/conductor/ai/document/DocumentAccessPolicy.java","lineNumber":289,"sourceCode":"    public void validateAccess(String location) {\n        if (disabled) {\n            return;\n        }\n\n        String normalized = normalizeLocation(location);\n\n        checkBlockedPaths(normalized);\n        checkBlockedFileNames(normalized);\n        checkBlockedHosts(location);\n        checkPathTraversal(normalized);\n        checkAllowedDirectories(location, normalized);\n    }\n\n    private void checkBlockedPaths(String normalizedPath) {\n        for (String prefix : DEFAULT_BLOCKED_PATH_PREFIXES) {\n            String expandedPrefix = expandHome(prefix);\n            if (normalizedPath.startsWith(expandedPrefix)) {\n                throw new DocumentAccessDeniedException(\n                        \"Access denied: path matches blocked prefix '\" + prefix + \"'\");\n            }\n        }\n        for (String prefix : blockedPathPrefixes) {\n            String expandedPrefix = expandHome(prefix);\n            if (normalizedPath.startsWith(expandedPrefix)) {\n                throw new DocumentAccessDeniedException(\n                        \"Access denied: path matches blocked prefix '\" + prefix + \"'\");\n            }\n        }\n    }\n\n    private void checkBlockedFileNames(String normalizedPath) {\n        String fileName = extractFileName(normalizedPath);\n        if (fileName == null || fileName.isEmpty()) {\n            return;\n        }\n        String lowerFileName = fileName.toLowerCase();","sourceCodeStart":271,"sourceCodeEnd":307,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/ai/src/main/java/org/conductoross/conductor/ai/document/DocumentAccessPolicy.java#L271-L307","documentation":"Thrown by DocumentAccessPolicy.checkBlockedPaths when a normalized local path starts with one of the built-in DEFAULT_BLOCKED_PATH_PREFIXES (e.g. /etc/shadow, ~/.ssh/, ~/.aws/, /var/run/secrets/). This is a hardcoded security denylist protecting against prompt-injection-driven exfiltration of OS credentials, cloud keys, and secret mounts. It is a DocumentAccessDeniedException (extends SecurityException).","triggerScenarios":"A document/retriever worker or upload tries to access a file path that falls under a built-in sensitive prefix — e.g. reading /etc/passwd, ~/.aws/credentials, /var/run/secrets/token, or ~/.kube/config as a 'document' for an LLM.","commonSituations":"An LLM tool or workflow was given an absolute path that happens to land in a protected tree; a default file-storage path was changed to something under ~/.docker or /etc; tests that point loaders at /etc/hosts.","solutions":["Move the file you legitimately need into a directory under the allowed list (file-storage parentDir or an allowed-directories entry) and reference it there.","If access is genuinely required and you accept the risk, the built-in list cannot be edited, so you must not place the file under a blocked prefix.","Double-check the path is not being constructed from user/LLM-controlled input that should be sandboxed instead."],"exampleFix":"// before\nloader.download(\"/root/.aws/credentials\")\n// after — read from an allowed, non-sensitive location\nloader.download(\"/data/imports/aws-config-copy.txt\")","handlingStrategy":"validation","validationCode":"// Pre-check a path against the same policy before invoking the loader\ntry {\n    accessPolicy.validateAccess(path);\n} catch (SecurityException e) {\n    log.warn(\"Rejecting blocked system path before loader call: {}\", path);\n    throw e;\n}","typeGuard":null,"tryCatchPattern":"try {\n    loader.download(path);\n} catch (SecurityException e) {\n    // built-in denylist — do NOT disable policy; refuse the path\n    throw new IllegalArgumentException(\"Path is blocked by security policy: \" + path, e);\n}","preventionTips":["Never disable DocumentAccessPolicy to work around a block — move the file under an allowed dir instead.","Do not place data you need under sensitive prefixes like ~/.ssh, ~/.aws, /etc, /var/run/secrets.","Treat paths from LLM/user input as untrusted; sanitize before any file access."],"tags":["security","ssrf","access-control","document-loader","denylist"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}