langchain-ai/deepagents · error · ValueError
Path traversal detected after normalization: {path} -> {norm
Error message
Path traversal detected after normalization: {path} -> {normalized} What it means
validate_path performs defense-in-depth path-traversal detection on a normalized path. If, after POSIX normalization (resolving '..' segments via normpath), any path component is still '..', the input could not be safely canonicalized, so a ValueError is raised to prevent reads/writes outside the intended root.
Source
Thrown at libs/deepagents/deepagents/backends/utils.py:718
if ".." in parts or path.startswith("~"):
msg = f"Path traversal not allowed: {path}"
raise ValueError(msg)
# Reject Windows absolute paths (e.g., C:\..., D:/...)
if re.match(r"^[a-zA-Z]:", path):
msg = f"Windows absolute paths are not supported: {path}. Please use virtual paths starting with / (e.g., /workspace/file.txt)"
raise ValueError(msg)
normalized = os.path.normpath(path)
normalized = normalized.replace("\\", "/")
if not normalized.startswith("/"):
normalized = f"/{normalized}"
# Defense-in-depth: verify normpath didn't produce traversal
if ".." in normalized.split("/"):
msg = f"Path traversal detected after normalization: {path} -> {normalized}"
raise ValueError(msg)
if allowed_prefixes is not None and not any(normalized.startswith(prefix) for prefix in allowed_prefixes):
msg = f"Path must start with one of {allowed_prefixes}: {path}"
raise ValueError(msg)
return normalized
def _normalize_path(path: str | None) -> str:
"""Normalize a path to canonical form.
Converts path to absolute form starting with /, removes trailing slashes
(except for root), and validates that the path is not empty.
Args:
path: Path to normalize (None defaults to "/")
Returns:View on GitHub (pinned to a1af029e6e)
Solutions
- Remove or resolve '..' segments before calling (posixpath.normpath on an absolute path).
- Ensure the path is absolute and rooted inside an allowed prefix (e.g. the workspace root).
- If the traversal is intentional, expand it yourself to the real absolute path and pass that.
- Wrap the call in try/except ValueError and surface a user-facing 'invalid path' message.
Example fix
// before
backend.read("../../etc/passwd")
// after
import posixpath
safe = posixpath.normpath(posixpath.join("/workspace", user_path))
if safe.startswith("/workspace"):
backend.read(safe) Defensive patterns
Strategy: validation
Validate before calling
import posixpath
def is_safe_path(user_path: str, root: str = "/workspace") -> bool:
absolute = posixpath.normpath(posixpath.join(root, user_path))
return absolute.startswith(root + "/") or absolute == root Type guard
def is_normalized_safe(normalized: str) -> bool:
return normalized.startswith("/") and ".." not in normalized.split("/") Try / catch
try:
backend.read(path)
except ValueError as exc:
if "traversal" in str(exc):
return {"error": f"Refusing unsafe path: {path}"}
raise Prevention
- Always normalize user-supplied paths with posixpath.normpath before passing to backend operations.
- Join user input onto a fixed root instead of accepting absolute paths.
- Keep '..' out of any path composed from external input.
- Add allowlist-prefix checks in your own tool wrappers before calling the backend.
When it happens
Trigger: Calling any backend file operation (ls, read, write, glob, grep) whose path argument, after normalization, still contains a '..' segment — e.g. validate_path('a/../../etc/passwd') when normalization cannot resolve the traversal, or paths built by joining user input with '..' fragments.
Common situations: Passing user/agent-supplied paths directly into backend operations; composing relative segments without sanitizing; sandboxed setups expecting paths under a workspace root but receiving escape paths.
Related errors
- Path traversal not allowed: {path}
- Invalid agent name: {agent_name!r}. Agent names can only con
- allow_fs_tools must be None or a non-empty list
- interpreter_ptc='all' exposes every host tool to PTC calls t
- temporary artifact is not a regular file
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/a6a261019a1f8d07.
Report an issue: GitHub.