langflow-ai/langflow · warning · HTTPException
Invalid fs_path: directory traversal (..) is not allowed
Error message
Invalid fs_path: directory traversal (..) is not allowed
What it means
HTTP 400: fs_path contained '..' after backslash-to-slash normalisation, i.e. an attempted directory traversal. The check runs on the normalised path, so both "../x" and "..\\x" forms are caught before any filesystem access, satisfying the CodeQL-recognised sanitiser pattern documented in the function.
Source
Thrown at src/backend/base/langflow/api/v1/flows_helpers.py:66
def _get_safe_flow_path(fs_path: str, user_id: UUID, storage_service: StorageService) -> Path:
"""Get a safe filesystem path for flow storage, restricted to user's flows directory.
Allows both absolute and relative paths, but ensures they're within the user's flows directory.
Uses ``os.path.realpath`` + ``startswith`` for containment — the sanitiser pattern
recognised by CodeQL's ``py/path-injection`` analysis. ``realpath`` canonicalises
the path and follows symlinks, so the returned path is safe to pass to filesystem
operations.
"""
if not fs_path:
raise HTTPException(status_code=400, detail="fs_path cannot be empty")
# Normalize path separators first (before security checks to prevent backslash bypass)
normalized_path = fs_path.replace("\\", "/")
# Reject directory traversal and null bytes (check normalized path)
if ".." in normalized_path:
raise HTTPException(
status_code=400,
detail="Invalid fs_path: directory traversal (..) is not allowed",
)
if "\x00" in normalized_path:
raise HTTPException(
status_code=400,
detail="Invalid fs_path: null bytes are not allowed",
)
# Build and canonicalise the safe base directory path.
base_dir = storage_service.data_dir / "flows" / str(user_id)
try:
base_dir_resolved = os.path.realpath(str(base_dir))
except (OSError, ValueError) as e:
raise HTTPException(status_code=400, detail=f"Invalid base directory: {e}") from e
# Determine if path is absolute (Unix or Windows style)
is_absolute = normalized_path.startswith("/") or (len(normalized_path) > 1 and normalized_path[1] == ":")View on GitHub (pinned to 976ec789d2)
Solutions
- Use a flat filename or a sub-path with no '..' segment: fs_path is always anchored under <data_dir>/flows/<user_id>/.
- Sanitise client-side: strip path segments equal to '..' before sending.
- If you genuinely need a file outside your flows dir, that is unsupported by design — copy the file into the flows directory instead.
Example fix
# before
{"fs_path": "../shared/flow.json"}
# after
{"fs_path": "shared/flow.json"} Defensive patterns
Strategy: validation
Validate before calling
if (fsPath.includes('..')) throw new Error('fs_path must not contain .. segments'); Type guard
const hasNoTraversal = (p: string) => !p.replace(/\\/g, '/').split('/').includes('..'); Prevention
- Send flat relative filenames
- Sanitise user input before placing it into fs_path
- Remember '..' anywhere in the string (even 'v2..old') is rejected
When it happens
Trigger: Any flow create/update where fs_path is "../secrets.json", "a/../../etc/passwd", or a backslash variant like "..\\..\\x"; also filename components that legitimately contain '..' (e.g. "v2..old.json") are rejected because the check is a plain substring match.
Common situations: Client builds the path from user input without sanitising; a flow exported from another instance contains an fs_path with parent references; filenames containing literal '..' (double-dot) sequences that are innocent but trip the substring check.
Related errors
- Invalid {label}. Use a simple {label} without directory path
- Invalid file entry
- Invalid file path format
- Invalid filename
- Invalid fs_path: null bytes are not allowed
AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14).
Data as JSON: /api/errors/8473edea5b167b8c.
Report an issue: GitHub.