langchain-ai/deepagents · error · ValueError

media path must not contain parent-directory traversal: {pat

Error message

media path must not contain parent-directory traversal: {path}

What it means

ValueError raised by resolve_bounded_media_path when the path contains '..' components (checked in both POSIX and Windows parsing). Parent-directory traversal is blocked to prevent paths escaping the outbound root.

Source

Thrown at libs/talon/deepagents_talon/media.py:223

    Raises:
        ValueError: If the path is unsafe, unavailable, or escapes `root`.
    """
    raw = str(path)
    parsed = urlparse(raw)
    windows_path = PureWindowsPath(raw)
    is_windows_drive_path = bool(windows_path.drive)
    if parsed.scheme and not is_windows_drive_path:
        msg = f"media path must be a local filesystem path: {path}"
        raise ValueError(msg)
    if raw.startswith("~") or (
        require_relative
        and (path.is_absolute() or windows_path.is_absolute() or is_windows_drive_path)
    ):
        msg = f"media path must be a local relative path under the outbound root: {path}"
        raise ValueError(msg)
    if ".." in path.parts or ".." in windows_path.parts:
        msg = f"media path must not contain parent-directory traversal: {path}"
        raise ValueError(msg)

    root_resolved = root.expanduser().resolve()
    candidate_input = root_resolved / path if not path.is_absolute() else path
    try:
        candidate = candidate_input.resolve(strict=True)
    except OSError as exc:
        msg = f"media file is unavailable: {path}"
        raise ValueError(msg) from exc
    if not candidate.is_relative_to(root_resolved):
        msg = f"media path escapes outbound root: {path}"
        raise ValueError(msg)
    if not candidate.is_file():
        msg = f"media path is not a regular file: {path}"
        raise ValueError(msg)
    return candidate


def _document_parts(paths: list[Path]) -> list[str]:

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Remove '..' components and pass a clean relative path under the outbound root
  2. Normalize user input with a sanitizer or reject names containing path separators/'..' before joining
  3. Use pathlib to join (root / name) with a validated bare filename

Example fix

// before
resolve_bounded_media_path(Path(f"uploads/{user_input}"), root)  # user_input="../x.png"
// after
name = Path(user_input).name  # strips directories/traversal
resolve_bounded_media_path(Path("uploads") / name, root)
Defensive patterns

Strategy: validation

Validate before calling

relative = Path(user_input)
if ".." in relative.parts or ".." in PureWindowsPath(user_input).parts:
    raise ValueError(f"traversal rejected: {user_input}")

Type guard

def is_safe_relative(p: Path) -> bool:
    return ".." not in p.parts and not p.is_absolute()

Try / catch

try:
    resolved = resolve_bounded_media_path(path, root)
except ValueError as exc:
    logger.warning("Rejected media path: %s", exc)
    return None

Prevention

When it happens

Trigger: Passing 'images/../../etc/passwd' or '..\\..\\secret.png' as media path.

Common situations: User-supplied filenames joined without sanitization; constructing paths with string concatenation that introduces '..'; path templates from untrusted input.

Related errors


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