langflow-ai/langflow · warning · HTTPException

Invalid flow filename

Error message

Invalid flow filename

What it means

Raised by _safe_resolved_path: after resolving the requested flow path with os.path.realpath and the flows base directory, the resolved path is neither the base itself nor under it (base + os.sep prefix). This is the path-traversal/symlink-escape guard (the pattern CodeQL's py/path-injection recognizes); any filename that escapes FLOWS_BASE_PATH — via '../', nested traversal, or a symlink inside the directory pointing outside — is rejected with HTTP 400.

Source

Thrown at src/backend/base/langflow/agentic/services/helpers/flow_loader.py:52

            yield
        finally:
            sys.path.remove(path)
    else:
        yield


def _safe_resolved_path(flow_path: Path) -> Path:
    """Resolve *flow_path* and confirm it stays within FLOWS_BASE_PATH.

    Uses ``os.path.realpath`` + ``startswith`` — the sanitiser pattern
    recognised by CodeQL's ``py/path-injection`` analysis — so the
    returned path is safe to pass to filesystem operations such as
    ``Path.exists()``. Raises HTTPException 400 on escape attempts.
    """
    base_resolved = os.path.realpath(str(FLOWS_BASE_PATH))
    resolved = os.path.realpath(str(flow_path))
    if resolved != base_resolved and not resolved.startswith(base_resolved + os.sep):
        raise HTTPException(status_code=400, detail="Invalid flow filename")
    return Path(resolved)


def resolve_flow_path(flow_filename: str) -> tuple[Path, str]:
    """Resolve flow filename to path and determine type.

    Supports both explicit extensions (.json, .py) and auto-detection.
    Priority: explicit extension > .py > .json

    Args:
        flow_filename: Name of the flow file (with or without extension).

    Returns:
        tuple[Path, str]: (resolved path, file type: "json" or "python")

    Raises:
        HTTPException: If flow file not found.
    """

View on GitHub (pinned to 976ec789d2)

Solutions

  1. Pass a bare filename (optionally with .json/.py) relative to FLOWS_BASE_PATH — no absolute paths, no '..'.
  2. On the server side, remove symlinks inside FLOWS_BASE_PATH that point outside the directory.
  3. In clients, strip/reject '..', backslashes, and leading '/' from flow_name before sending.

Example fix

// before
fetch(`/api/v1/agentic/execute/${encodeURIComponent('../../secrets/flow.json')}`)
// after
fetch(`/api/v1/agentic/execute/${encodeURIComponent('my-flow.json')}`)
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def safe_flow_name(name: str) -> bool:
    return bool(name) and '..' not in name and '\\' not in name and not name.startswith('/') and Path(name).name == name

Type guard

const isSafeFlowName = (n: string): boolean =>
  /^[A-Za-z0-9_.-]+$/.test(n) && !n.includes('..');

Try / catch

On 400 'Invalid flow filename', log it as a potential attack/probe and never echo the requested name back to end users.

Prevention

When it happens

Trigger: Calling an agentic execute endpoint with flow_name like 'sub/../../etc/passwd', 'flows/../../../home/user/secret.json', or a filename that resolves through a symlink planted in the flows directory to a file outside it.

Common situations: Probing attacks against deployments that pass user input straight into flow_name; legitimate-looking names containing URL-encoded traversal that survived decoding; a symlinked flow file in the directory for 'shared' flows; copy-pasting an absolute path as flow_name.

Related errors


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