langflow-ai/langflow · error · HTTPException
Invalid filename
Error message
Invalid filename
What it means
validate_public_files() rejects a file reference whose basename is exactly '.' after the path already passed the format and namespace checks. It is part of the hardening for GHSA-rcjh-r59h-gq37, which restricted unauthenticated public-flow builds to file paths of the form {source_flow_id}/{basename}. Although the '..' substring is already rejected earlier, a lone '.' basename (the current directory) is blocked here as an extra guard so anonymous callers cannot address the flow's directory itself.
Source
Thrown at src/backend/base/langflow/api/utils/flow_utils.py:171
Called from any endpoint that accepts caller-supplied file references
under a public-access boundary.
"""
if not files:
return
expected_flow_id = str(source_flow_id).lower()
for entry in files:
if not isinstance(entry, str) or not entry:
raise HTTPException(status_code=400, detail="Invalid file entry")
if any(token in entry for token in _PUBLIC_FILE_REJECTED_SUBSTRINGS):
raise HTTPException(status_code=400, detail="Invalid file path")
match = _PUBLIC_FILE_PATH_RE.match(entry)
if not match:
raise HTTPException(status_code=400, detail="Invalid file path format")
flow_id_segment, basename = match.group(1), match.group(2)
if flow_id_segment.lower() != expected_flow_id:
raise HTTPException(status_code=400, detail="File not in this flow's namespace")
if basename in (".", ".."):
raise HTTPException(status_code=400, detail="Invalid filename")
def compute_virtual_flow_id(
identifier: str | uuid.UUID,
flow_id: uuid.UUID,
*,
principal_type: Literal["user", "client"] | None = None,
) -> uuid.UUID:
"""Compute a deterministic virtual flow ID for session/message isolation.
Args:
identifier: A unique identifier (user_id for authenticated users, client_id for anonymous).
flow_id: The original flow ID.
principal_type: Optional identity domain for public-flow callers. Authenticated
user IDs and anonymous client IDs must never share a UUID namespace.
Returns:
A deterministic UUID v5 derived from the identifier and flow_id.View on GitHub (pinned to 976ec789d2)
Solutions
- Fix the client to send only plain basenames under the flow's own UUID, e.g. '{flow_id}/report.pdf' — never '.' or '..'.
- If you construct paths programmatically, split on '/' and drop empty components instead of using normpath before sending to the API.
- If you legitimately need directory-like grouping, upload under a flattened name (e.g. 'folder_report.pdf'); the API only accepts a single path segment.
- If you operate the server and see floods of these, treat them as probes of GHSA-rcjh-r59h-gq37 and rate-limit the endpoint.
Example fix
# before
files = [f"{flow_id}/{os.path.normpath(rel_path)}"] # normpath('....') can yield '.'
# after
rel = rel_path.strip('/').split('/')[-1] # keep basename only
if rel in ('.', '..'):
raise ValueError(f"bad file path: {rel_path}")
files = [f"{flow_id}/{rel}"] Defensive patterns
Strategy: validation
Validate before calling
import re
PATH_RE = re.compile(r'^([0-9a-fA-F-]{36})/([^/\\]+)$')
def safe_public_files(files, flow_id):
fid = str(flow_id).lower()
out = []
for f in files or []:
m = PATH_RE.match(f)
if (not m or m.group(1).lower() != fid or m.group(2) in ('.', '..')
or any(t in f for t in ('..', '\\', '\x00'))):
raise ValueError(f'unsafe file entry: {f!r}')
out.append(f)
return out Try / catch
try:
validate_public_files(files, flow_id)
except HTTPException as e:
if e.status_code == 400 and e.detail == 'Invalid filename':
# strip '.'/'..' entries client-side and rebuild the list
...
raise Prevention
- Build file references as f'{flow_id}/{basename}' from a trusted basename only.
- Never run os.path.normpath on entries before sending — it can produce '.'.
- Reject '.', '..' and empty segments client-side before the request.
When it happens
Trigger: A caller of a public-flow build/upload endpoint passes a files list entry like '3f0b.../.' (flow UUID matching the public flow, basename exactly '.'). Note that entries containing '..' anywhere, backslashes, NUL bytes, non-UUID prefixes, or a foreign flow UUID fail earlier with 'Invalid file path'/'Invalid file path format'/'File not in this flow's namespace' instead.
Common situations: Client code that builds file paths by string concatenation (os.path.join or f-strings) and accidentally appends an empty segment; scripts replaying captured upload requests after path normalization (os.path.normpath turns './' into '.'); crafted probes against a shared public flow trying to escape the {flow_id}/ namespace.
Related errors
- Invalid {label}. Use a simple {label} without directory path
- Invalid file entry
- Invalid file path format
- Invalid fs_path: directory traversal (..) is not allowed
- Invalid path
AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14).
Data as JSON: /api/errors/5d7904018bfada67.
Report an issue: GitHub.