{"record":{"id":"3f20d12962bcd1e0","repo":"langflow-ai/langflow","slug":"invalid-flow-filename","errorCode":null,"errorMessage":"Invalid flow filename","messagePattern":"Invalid flow filename","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"src/backend/base/langflow/agentic/services/helpers/flow_loader.py","lineNumber":52,"sourceCode":"            yield\n        finally:\n            sys.path.remove(path)\n    else:\n        yield\n\n\ndef _safe_resolved_path(flow_path: Path) -> Path:\n    \"\"\"Resolve *flow_path* and confirm it stays within FLOWS_BASE_PATH.\n\n    Uses ``os.path.realpath`` + ``startswith`` — the sanitiser pattern\n    recognised by CodeQL's ``py/path-injection`` analysis — so the\n    returned path is safe to pass to filesystem operations such as\n    ``Path.exists()``. Raises HTTPException 400 on escape attempts.\n    \"\"\"\n    base_resolved = os.path.realpath(str(FLOWS_BASE_PATH))\n    resolved = os.path.realpath(str(flow_path))\n    if resolved != base_resolved and not resolved.startswith(base_resolved + os.sep):\n        raise HTTPException(status_code=400, detail=\"Invalid flow filename\")\n    return Path(resolved)\n\n\ndef resolve_flow_path(flow_filename: str) -> tuple[Path, str]:\n    \"\"\"Resolve flow filename to path and determine type.\n\n    Supports both explicit extensions (.json, .py) and auto-detection.\n    Priority: explicit extension > .py > .json\n\n    Args:\n        flow_filename: Name of the flow file (with or without extension).\n\n    Returns:\n        tuple[Path, str]: (resolved path, file type: \"json\" or \"python\")\n\n    Raises:\n        HTTPException: If flow file not found.\n    \"\"\"","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/src/backend/base/langflow/agentic/services/helpers/flow_loader.py#L34-L70","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass a bare filename (optionally with .json/.py) relative to FLOWS_BASE_PATH — no absolute paths, no '..'.","On the server side, remove symlinks inside FLOWS_BASE_PATH that point outside the directory.","In clients, strip/reject '..', backslashes, and leading '/' from flow_name before sending."],"exampleFix":"// before\nfetch(`/api/v1/agentic/execute/${encodeURIComponent('../../secrets/flow.json')}`)\n// after\nfetch(`/api/v1/agentic/execute/${encodeURIComponent('my-flow.json')}`)","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef safe_flow_name(name: str) -> bool:\n    return bool(name) and '..' not in name and '\\\\' not in name and not name.startswith('/') and Path(name).name == name","typeGuard":"const isSafeFlowName = (n: string): boolean =>\n  /^[A-Za-z0-9_.-]+$/.test(n) && !n.includes('..');","tryCatchPattern":"On 400 'Invalid flow filename', log it as a potential attack/probe and never echo the requested name back to end users.","preventionTips":["Whitelist flow names to a strict charset (letters, digits, dash, underscore, dot).","Never build flow_name from raw user input or URL fragments.","Keep FLOWS_BASE_PATH free of symlinks pointing outside itself."],"tags":["agentic","path-traversal","security","http-400","flow-loader"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}