langflow-ai/langflow · warning · HTTPException

Invalid flow filename: '{flow_filename}'

Error message

Invalid flow filename: '{flow_filename}'

What it means

First-line defense in resolve_flow_path: any flow_filename containing '..' or a backslash is rejected with HTTP 400 before any path is constructed. It complements the realpath-based check in _safe_resolved_path, catching obvious traversal payloads early (including Windows-style separators) so they never reach filesystem APIs.

Source

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

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.
    """
    # Early rejection of path traversal sequences before any path construction.
    if ".." in flow_filename or "\\" in flow_filename:
        raise HTTPException(status_code=400, detail=f"Invalid flow filename: '{flow_filename}'")

    if flow_filename.endswith(".json"):
        flow_path = _safe_resolved_path(FLOWS_BASE_PATH / flow_filename)
        if flow_path.exists():
            return flow_path, "json"
        raise HTTPException(status_code=404, detail=f"Flow file '{flow_filename}' not found")

    if flow_filename.endswith(".py"):
        flow_path = _safe_resolved_path(FLOWS_BASE_PATH / flow_filename)
        if flow_path.exists():
            return flow_path, "python"
        raise HTTPException(status_code=404, detail=f"Flow file '{flow_filename}' not found")

    # Auto-detect: try Python first, then JSON (allows gradual migration)
    base_name = flow_filename.rsplit(".", 1)[0] if "." in flow_filename else flow_filename

    py_path = _safe_resolved_path(FLOWS_BASE_PATH / f"{base_name}.py")
    if py_path.exists():

View on GitHub (pinned to 976ec789d2)

Solutions

  1. Send only the bare file name relative to the flows directory (e.g. 'assistant.json').
  2. Sanitize client-side: reject strings containing '..', '\\', or '/' where subdirectories are not intended.
  3. If you administer the server, treat repeated 400s of this shape as probing and monitor them.

Example fix

# before
name = '../../shared/assistant.json'
# after
name = 'assistant.json'  # must live directly under FLOWS_BASE_PATH
Defensive patterns

Strategy: validation

Validate before calling

const clean = (name) => {
  if (/[.]{2}|\\|\//.test(name)) throw new Error(`unsafe flow name: ${name}`);
  return name;
};

Type guard

const hasNoTraversal = (n: string): boolean => !n.includes('..') && !n.includes('\\');

Try / catch

Reject client-side before the request; if the server still returns 400 'Invalid flow filename', treat the input path as hostile and halt.

Prevention

When it happens

Trigger: GET/POST to an agentic execute endpoint with flow_name such as '../app/flows/x.json', 'a\b.json', or '..%2F..%2Fetc%2Fpasswd' after URL decoding; the substring check fires regardless of whether the path would actually escape.

Common situations: Attackers probing for traversal; clients accidentally passing OS paths ('C:\flows\x.json' or 'flows/../flows/x.json'); filenames copied from error messages that include relative prefixes.

Related errors


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