langchain-ai/deepagents · error · ValueError
Path traversal not allowed
Error message
Path traversal not allowed
What it means
In virtual mode, FilesystemBackend resolves every key against its root directory and rejects paths that escape it. Any path containing a '..' segment or starting with '~' is refused up front with ValueError to keep the backend sandboxed to its root.
Source
Thrown at libs/deepagents/deepagents/backends/filesystem.py:207
When `virtual_mode=False`, preserve legacy behavior: absolute paths are allowed
as-is; relative paths resolve under cwd.
Args:
key: File path (absolute, relative, or virtual when `virtual_mode=True`).
Returns:
Resolved absolute `Path` object.
Raises:
ValueError: If path traversal is attempted in `virtual_mode` or if the
resolved path escapes the root directory.
OSError: If the path is a symlink loop (`ELOOP`).
"""
if self.virtual_mode:
vpath = key if key.startswith("/") else "/" + key
if ".." in vpath or vpath.startswith("~"):
msg = "Path traversal not allowed"
raise ValueError(msg)
full = (self.cwd / vpath.lstrip("/")).resolve()
try:
full.relative_to(self.cwd)
except ValueError:
msg = f"Path:{full} outside root directory: {self.cwd}"
raise ValueError(msg) from None
_raise_if_symlink_loop(full)
return full
path = Path(key)
if path.is_absolute():
_raise_if_symlink_loop(path)
return path
resolved = (self.cwd / path).resolve()
_raise_if_symlink_loop(resolved)
return resolved
def _to_virtual_path(self, path: Path) -> str:View on GitHub (pinned to a1af029e6e)
Solutions
- Remove '..' segments and resolve to a path relative to the backend root before calling
- Expand '~' yourself and pass the resulting path rooted inside the backend directory
- Normalize the path (os.path.normpath / Path.resolve) and verify it stays under the intended root
- If you truly need access outside the root, reconfigure the backend root_dir instead of traversing
Example fix
// before
backend.read("../settings.json")
// after
backend.read("settings.json") # relative to backend root Defensive patterns
Strategy: validation
Validate before calling
from pathlib import PurePosixPath
def is_safe_key(key: str) -> bool:
p = PurePosixPath(key.lstrip("/"))
return ".." not in p.parts and not key.startswith("~")
assert is_safe_key(user_path), "refusing traversal path" Type guard
def safe_backend_key(key: str) -> str | None:
parts = PurePosixPath(key.lstrip("/")).parts
return key if ".." not in parts and not key.startswith("~") else None Try / catch
try:
content = backend.read(key)
except ValueError as exc:
if "Path traversal not allowed" in str(exc):
content = None # or re-resolve the key against the root
else:
raise Prevention
- Never forward raw LLM/user-supplied paths directly to backend calls
- Normalize keys with PurePosixPath and drop '..' segments first
- Keep all file references relative to the backend root
When it happens
Trigger: Calling ls, read, write, edit, delete, or grep with a key like '../secrets.txt', 'a/../../etc/passwd', or '~/config' while the backend is in virtual_mode.
Common situations: LLM-generated paths containing '..', joining user input with a relative base, or shell-style '~/file' expansion habits applied to backend keys.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- Path:{full} outside root directory: {self.cwd}
- Permission path must not contain '..': {path!r}
- debug log directory is not a real directory: {path}
- debug log directory is not owned by the current user: {path}
- Cannot determine whether {str(left)!r} is {str(right)!r}: {e
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/b321e4fbbf720916.
Report an issue: GitHub.