langflow-ai/langflow · error · HTTPException

Invalid path

Error message

Invalid path

What it means

The agentic file-read router validates the requested path shape before any I/O: traversal ('..'), absolute paths, null bytes, and similar malformed shapes raise HTTP 400 'Invalid path'. This is _is_unsafe_path_shape rejecting the string itself, independent of whether the file exists. It uses the same security primitives as the agent's FileSystemToolComponent rather than a parallel implementation.

Source

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

    *,
    current_user: CurrentActiveUser,
    path: Annotated[str, Query(min_length=1, max_length=_MAX_PATH_LENGTH)],
    download: Annotated[bool, Query()] = False,
) -> Response:
    """Return the contents of a sandboxed file as text (or as an attachment).

    Raises:
        HTTPException(400): The path shape is invalid (traversal, absolute,
            null byte, etc.). No I/O is attempted.
        HTTPException(404): The file does not exist in the requesting user's
            sandbox. Same status for sandbox-internal "not found" and for
            "path resolves outside the user namespace" — by design, to avoid
            leaking namespace existence to another tenant.
        HTTPException(413): The file is larger than ``MAX_FILE_SIZE_BYTES``.
        HTTPException(415): The file is binary (null byte in the first 8 KiB).
    """
    if _is_unsafe_path_shape(path):
        raise HTTPException(status_code=400, detail="Invalid path")

    # Deferred import: FileSystemToolComponent pulls a chunk of lfx — we don't
    # want every router-import path to do it eagerly. We use the **same**
    # security primitives the agent's tools use, not a parallel implementation.
    from lfx.components.files_and_knowledge.filesystem import (
        BINARY_SNIFF_BYTES,
        MAX_FILE_SIZE_BYTES,
        FileSystemToolComponent,
        _looks_binary,
        _read_bytes_no_follow,
        _read_head_no_follow,
    )

    fs = FileSystemToolComponent()
    fs._user_id = str(current_user.id)  # noqa: SLF001 — bind sandbox to caller
    # 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/`

View on GitHub (pinned to 976ec789d2)

Solutions

  1. Send a relative path under the user's sandbox, e.g. 'notes/todo.md' with no leading '/' and no '..' segments.
  2. Normalize client-side: strip absolute prefixes and reject '..' before calling the API.
  3. Treat 400 as a client bug — fix the path producer (often the model/tool prompt) rather than retrying.

Example fix

# before
GET /api/v1/agentic/files?path=/home/user/sandbox/notes.md  # 400 Invalid path
# after
GET /api/v1/agentic/files?path=notes.md
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import PurePosixPath

def safe_sandbox_path(p: str) -> bool:
    if not p or "\x00" in p:
        return False
    pp = PurePosixPath(p)
    return not pp.is_absolute() and not any(part in ("..", "") for part in pp.parts) and "\\" not in p

Try / catch

if resp.status_code == 400 and resp.json().get("detail") == "Invalid path":
    log_and_sanitize_the_path_producer()  # fix the generator (often LLM output), don't retry

Prevention

When it happens

Trigger: GET /api/v1/agentic/files?path=../../etc/passwd, path=/etc/hosts (absolute), or a path containing a null byte.

Common situations: LLM-generated tool output containing absolute or traversal paths fed straight into the API; clients joining user input with an OS path separator producing a leading slash; probing/pen-test payloads.

Related errors


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