langflow-ai/langflow · error · HTTPException

Not found

Error message

Not found

What it means

During agentic file reads, fs._validate_path raises PermissionError when the path escapes the requesting user's sandbox, hits a deny-list, or otherwise violates sandbox boundaries. The router deliberately maps this to HTTP 404 (not 403) so a cross-tenant probe cannot learn whether a namespace exists. The refusal is logged (user id, path, reason) at warning level.

Source

Thrown at src/backend/base/langflow/agentic/api/files_router.py:149

    # B1: this endpoint carries an authenticated user identity and must
    # always resolve a per-user sandbox root, even under AUTO_LOGIN=True
    # (otherwise two users on a shared deployment read the same `shared/`
    # tree). The agent's write tools set the same flag in build_toolkit so
    # write and read paths resolve to the SAME users/<hash>/ root.
    fs._force_isolation = True  # noqa: SLF001 — security: see filesystem._validate_root
    try:
        resolved = fs._validate_path(path)  # noqa: SLF001 — public sandbox entry
    except PermissionError as exc:
        # _validate_root / _validate_path raise PermissionError on sandbox
        # boundary violations (path escape, deny-list, etc.). Map to 404 so we
        # never leak namespace existence to another tenant.
        logger.warning(
            "agentic.files.read.refused user_id=%s path=%s reason=%s",
            current_user.id,
            path,
            exc,
        )
        raise HTTPException(status_code=404, detail="Not found") from None

    if not resolved.exists() or resolved.is_dir():
        logger.warning(
            "agentic.files.read.missing user_id=%s path=%s resolved=%s exists=%s is_dir=%s",
            current_user.id,
            path,
            resolved,
            resolved.exists(),
            resolved.is_dir(),
        )
        raise HTTPException(status_code=404, detail="Not found")

    try:
        size = resolved.stat().st_size
    except OSError:
        raise HTTPException(status_code=404, detail="Not found") from None
    if size > MAX_FILE_SIZE_BYTES:
        raise HTTPException(status_code=413, detail="File too large")

View on GitHub (pinned to 976ec789d2)

Solutions

  1. Request only files that physically live inside your sandbox; remove symlinks that point outside it.
  2. If you administer the deployment, check the warn log (agentic.files.read.refused ... reason=...) to see the boundary rule that fired.
  3. Do not retry — 404 here is a policy refusal, not a transient miss.

Example fix

# before
GET /api/v1/agentic/files?path=data/../../other_user/secret.md  # 404 Not found (sandbox refusal)
# after
GET /api/v1/agentic/files?path=data/secret.md
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def inside_sandbox(root: Path, target: Path) -> bool:
    try:
        target.resolve().relative_to(root.resolve())
        return not target.is_symlink() or inside_sandbox(root, target.resolve())
    except ValueError:
        return False

Prevention

When it happens

Trigger: Requesting a path with '..' segments that survive shape validation, symlinks pointing outside the sandbox, or deny-listed locations.

Common situations: Symlink inside the sandbox pointing at /etc or another user's tree; agent-generated paths attempting escape; shared-hosting style probing between tenants.

Related errors


AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14). Data as JSON: /api/errors/ba09566d0a2924cb. Report an issue: GitHub.