Mintplex-Labs/anything-llm · error · Error
Access denied - symlink target outside allowed directories.
Error message
Access denied - symlink target outside allowed directories.
What it means
Thrown by validatePath() after fs.realpath() resolves the requested path to a real target that lies OUTSIDE the allowed directories. This catches symlink-escape attempts where the path itself appears inside the workspace but ultimately points elsewhere. Distinct from 394, which fires before realpath; this fires after, on the resolved target.
Source
Thrown at server/utils/agents/aibitat/plugins/filesystem/lib.js:444
console.log(
`[validatePath] Access denied - path outside allowed directories: ${absolute} not in ${this.#allowedDirectories.join(", ")}`
);
throw new Error(`Access denied - path outside allowed directories.`);
}
try {
const realPath = await fs.realpath(absolute);
const normalizedReal = this.#normalizePath(realPath);
if (
!this.#isPathWithinAllowedDirectories(
normalizedReal,
this.#allowedDirectories
)
) {
console.log(
`[validatePath] Access denied - symlink target outside allowed directories: ${realPath} not in ${this.#allowedDirectories.join(", ")}`
);
throw new Error(
`Access denied - symlink target outside allowed directories.`
);
}
return realPath;
} catch (error) {
if (error.code === "ENOENT") {
const parentDir = path.dirname(absolute);
try {
const realParentPath = await fs.realpath(parentDir);
const normalizedParent = this.#normalizePath(realParentPath);
if (
!this.#isPathWithinAllowedDirectories(
normalizedParent,
this.#allowedDirectories
)
) {
console.log(
`[validatePath] Access denied - parent directory outside allowed directories: ${realParentPath} not in ${this.#allowedDirectories.join(", ")}`View on GitHub (pinned to 526360e320)
Solutions
- Remove or rewrite the offending symlink so its target is within an allowed directory.
- Audit the workspace for symlinks pointing outside (find -type l).
- Do not create symlinks in the workspace that escape the sandbox.
Defensive patterns
Strategy: try-catch
Validate before calling
const fs = require("fs/promises");
async function assertSymlinkTargetInside(p, allowedDirs) {
const st = await fs.lstat(p);
if (st.isSymbolicLink()) {
const target = await fs.realpath(p);
if (!allowedDirs.some((d) => target.startsWith(path.resolve(d))))
throw new Error(`Symlink ${p} escapes workspace`);
}
} Try / catch
try { await filesystem.validatePath(p); }
catch (e) {
if (e.message.includes("symlink target outside")) { /* remove the offending link */ }
else throw e;
} Prevention
- Do not place symlinks in the workspace that point outside it.
- Audit the workspace for escaping symlinks before filesystem operations.
- Treat realpath-resolved targets as untrusted until confirmed inside the sandbox.
When it happens
Trigger: A path inside the allowed workspace that is a symlink whose target resolves outside the workspace (e.g., workspace/secret -> /etc). The normalized requested path passes the first check, but realpath reveals the true destination is forbidden.
Common situations: A malicious or accidental symlink planted in the workspace pointing to system files; a symlink chain that eventually leaves the workspace; an agent or user creating a link to shortcut access to outside files.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Access denied - parent directory outside allowed directories
- Access denied - path outside allowed directories.
- Cannot copy symbolic link: ${source}. Symlinks are not allow
- Invalid path.
- Invalid path name
AI-assisted analysis of Mintplex-Labs/anything-llm@526360e320 (2026-08-13).
Data as JSON: /api/errors/729782da75dd8bd8.
Report an issue: GitHub.