langflow-ai/langflow · warning · HTTPException

Absolute path must be within your flows directory

Error message

Absolute path must be within your flows directory

What it means

HTTP 400: the submitted fs_path was absolute (starts with '/' or a Windows drive letter like 'C:') and, after realpath canonicalisation, does not lie inside <data_dir>/flows/<user_id>. The containment check (realpath + startswith with os.sep) is the CodeQL-recognised sanitiser; absolute paths are permitted only if they resolve inside the user's own flows directory.

Source

Thrown at src/backend/base/langflow/api/v1/flows_helpers.py:101

    # Determine if path is absolute (Unix or Windows style)
    is_absolute = normalized_path.startswith("/") or (len(normalized_path) > 1 and normalized_path[1] == ":")

    if is_absolute:
        candidate = normalized_path
    else:
        relative_part = normalized_path.lstrip("/")
        # os.path.join is deliberate here (PTH118) to match CodeQL's sanitiser model.
        candidate = os.path.join(base_dir_resolved, relative_part) if relative_part else base_dir_resolved  # noqa: PTH118

    try:
        resolved_str = os.path.realpath(candidate)
    except (OSError, ValueError) as e:
        raise HTTPException(status_code=400, detail=f"Invalid path: {e}") from e

    # SECURITY: containment check using os.path.realpath + startswith (CodeQL-recognised).
    if resolved_str != base_dir_resolved and not resolved_str.startswith(base_dir_resolved + os.sep):
        if is_absolute:
            raise HTTPException(
                status_code=400,
                detail="Absolute path must be within your flows directory",
            )
        raise HTTPException(
            status_code=400,
            detail="Invalid path: resolves outside allowed directory",
        )

    # Return the canonicalised path — safe for subsequent filesystem operations.
    return Path(resolved_str)


# Fields that may be updated via setattr on a Flow ORM instance.
# Any key not in this set is silently dropped to prevent callers from
# overwriting internal fields (e.g. ``id``, ``user_id``).
_UPDATABLE_FLOW_FIELDS: frozenset[str] = frozenset(
    {
        "name",

View on GitHub (pinned to 976ec789d2)

Solutions

  1. Send a relative fs_path ("my_flow.json"); it is automatically anchored under your flows directory.
  2. If absolute is required, it must resolve inside <data_dir>/flows/<your user id>/.
  3. When importing legacy flows, strip the old absolute prefix and keep just the basename.

Example fix

# before
{"fs_path": "/home/olduser/langflow/flows/my_flow.json"}
# after
{"fs_path": "my_flow.json"}
Defensive patterns

Strategy: validation

Validate before calling

if (/^(\/|[A-Za-z]:)/.test(fsPath)) throw new Error('send relative fs_path only');

Type guard

const isRelativeFsPath = (p: string) => !p.startsWith('/') && !/^[A-Za-z]:/.test(p.replace(/\\/g,'/'));

Prevention

When it happens

Trigger: POST/PATCH /api/v1/flows with fs_path="/etc/passwd", "C:\\Users\\me\\flow.json", or any absolute path outside data_dir/flows/<user_id>; also an absolute path that IS inside the dir textually but escapes via a symlink.

Common situations: Client migrates flows from an old instance that stored absolute paths and resubmits them verbatim on a new host; users pasting a local filesystem path into an fs_path field; pen-test probing for arbitrary file write.

Related errors


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