langchain-ai/deepagents · error · ValueError

Path traversal not allowed: {path}

Error message

Path traversal not allowed: {path}

What it means

`validate_path` normalizes virtual filesystem paths and rejects anything that escapes the virtual root. A `..` path component or a leading `~` raises ValueError 'Path traversal not allowed'. The check is per path component (not substring), so legitimate names like `foo..bar.txt` still pass.

Source

Thrown at libs/deepagents/deepagents/backends/utils.py:702

            Windows absolute path (e.g., `C:/...`), or does not start with an
            allowed prefix when `allowed_prefixes` is specified.

    Example:
        ```python
        validate_path("foo/bar")  # Returns: "/foo/bar"
        validate_path("/./foo//bar")  # Returns: "/foo/bar"
        validate_path("../etc/passwd")  # Raises ValueError
        validate_path(r"C:\\Users\\file.txt")  # Raises ValueError
        validate_path("/data/file.txt", allowed_prefixes=["/data/"])  # OK
        validate_path("/etc/file.txt", allowed_prefixes=["/data/"])  # Raises ValueError
        ```
    """
    # Check for traversal as a path component (not substring) to avoid
    # false-positive rejection of legitimate filenames like "foo..bar.txt"
    parts = PurePosixPath(to_posix_path(path)).parts
    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):

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Use absolute virtual paths rooted at `/` (e.g. `/workspace/file.txt`) without `..` or `~` components
  2. Resolve/normalize paths against an explicit base directory yourself and verify containment before calling the backend
  3. Sanitize user/LLM input: strip `~`, collapse or reject `..` components
  4. Catch the ValueError and return a friendly tool-error telling the agent to use virtual paths

Example fix

// before
backend.read('~/secrets.txt')
backend.read('/workspace/../etc/passwd')
// after
backend.read('/workspace/notes.txt')
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import PurePosixPath
def is_safe_virtual_path(path: str) -> bool:
    if path.startswith('~'):
        return False
    parts = PurePosixPath(path.replace('\\', '/')).parts
    if '..' in parts:
        return False
    return True

if is_safe_virtual_path(p):
    backend.read(p)

Type guard

def is_safe_path(path: object) -> bool:
    if not isinstance(path, str) or path.startswith('~'):
        return False
    from pathlib import PurePosixPath
    return '..' not in PurePosixPath(path.replace('\\', '/')).parts

Try / catch

try:
    content = backend.read(path)
except ValueError as exc:
    if 'Path traversal not allowed' in str(exc):
        raise ToolError(f'use absolute /-rooted virtual paths, got {path!r}') from exc
    raise

Prevention

When it happens

Trigger: Calling backend `read`/`write`/`ls`/`edit`/`glob` with paths like `/../etc/passwd`, `a/../../b`, or `~/notes.txt`; LLM-generated tool arguments containing `..` or `~`; user input interpolated unvalidated into paths.

Common situations: Agents hallucinating home-relative (`~`) paths; users pasting shell-style paths; composing paths from user-controlled directory names without sanitization.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/7d6a116fbdcda201. Report an issue: GitHub.