langflow-ai/langflow · error · HTTPException
Invalid path: resolves outside allowed directory
Error message
Invalid path: resolves outside allowed directory
What it means
HTTP 400: the (relative) fs_path resolved via realpath to a location outside <data_dir>/flows/<user_id> — i.e. it escapes the allowed directory even though it contained no '..'. This is the symlink-escape branch: a symlink inside the flows dir pointing elsewhere makes the canonicalised path fail the startswith containment check.
Source
Thrown at src/backend/base/langflow/api/v1/flows_helpers.py:105
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",
"description",
"data",
"is_component",
"endpoint_name",View on GitHub (pinned to 976ec789d2)
Solutions
- Remove or fix symlinks under <data_dir>/flows/<user_id>/ so every entry is a real file/subdirectory.
- Copy the target file into the flows directory instead of symlinking it.
- Use a plain relative filename with no directory components to avoid touching any symlinks.
Example fix
# server-side, before: flows/<uid>/shared -> /srv/shared (symlink) # after: real directory cp -rL /srv/shared /data/flows/<uid>/shared # dereference into a real dir
Defensive patterns
Strategy: validation
Validate before calling
find /data/flows/<user_id> -type l # empty output means no symlink-escape risk
Prevention
- Keep the flows directory symlink-free (real files and dirs only)
- Copy shared files in rather than symlinking
- Monitor the flows dir for planted symlinks in multi-tenant setups
When it happens
Trigger: A file or directory under flows/<user_id>/ is a symlink to somewhere outside (e.g. "shared" -> "/etc"), and fs_path goes through it; or a race where the path changed between join and realpath; also any relative path that textually stays inside but canonically lands outside.
Common situations: Admin or user created symlinks inside the storage dir to share files or save disk; container setups where the flows dir contains mount-point symlinks; attackers planting a symlink to escalate the write outside the sandbox.
Related errors
- Absolute path must be within your flows directory
- Invalid fs_path: directory traversal (..) is not allowed
- Invalid fs_path: null bytes are not allowed
- Invalid flow filename
- Invalid flow filename: '{flow_filename}'
AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14).
Data as JSON: /api/errors/4846d78eb3791764.
Report an issue: GitHub.