abi/screenshot-to-code · error · InvalidSetNameError
Invalid image path: {filename!r}
Error message
Invalid image path: {filename!r} What it means
resolve_set_image_path raises InvalidSetNameError("Invalid image path") when the realpath of inputs_dir + basename(filename) escapes the realpath'd inputs directory. This is the path-traversal guard: although basename() already strips directory components, a symlinked file inside inputs/ whose target lives outside would still resolve outside, and the prefix check catches that. It fires when the resolved path does not start with realpath(inputs_dir) + os.sep.
Source
Thrown at backend/evals/sets.py:300
os.path.isdir(os.path.join(set_dir, "inputs"))
or os.path.isfile(os.path.join(set_dir, "briefs.json"))
):
continue
infos.append(get_set(entry))
return infos
def resolve_set_image_path(set_name: str, filename: str) -> str:
"""Absolute path of a set image; raises on traversal or missing file."""
inputs_dir = get_set_inputs_dir(set_name)
if not os.path.isdir(inputs_dir):
raise EvalSetNotFoundError(f"Eval set not found: {set_name}")
safe_name = os.path.basename(filename)
if not safe_name.lower().endswith(".png"):
raise InvalidSetNameError(f"Not a set image: {filename!r}")
path = os.path.realpath(os.path.join(inputs_dir, safe_name))
if not path.startswith(os.path.realpath(inputs_dir) + os.sep):
raise InvalidSetNameError(f"Invalid image path: {filename!r}")
if not os.path.isfile(path):
raise FileNotFoundError(path)
return path
View on GitHub (pinned to d026163f58)
Solutions
- Replace symlinks in inputs/ with real file copies (cp -L).
- If shared images are needed, copy them into the set directory.
- Caller-side, reject any filename containing '/' or '..' before calling resolve.
Example fix
# before ln -s ~/shared/shot.png sets/my-set/inputs/shot.png # after cp ~/shared/shot.png sets/my-set/inputs/shot.png
Defensive patterns
Strategy: validation
Validate before calling
import os
def is_safe_image_filename(filename: str) -> bool:
base = os.path.basename(filename)
return (
base == filename
and "/" not in filename
and "\\" not in filename
and ".." not in filename
and base.lower().endswith(".png")
) Try / catch
try:
path = resolve_set_image_path(set_name, filename)
except InvalidSetNameError as e:
abort(400, description=str(e)) # traversal or non-png: client error, not 500 Prevention
- Never put symlinks in a set's inputs/ — copy files instead
- Pass plain filenames from os.listdir, not user-supplied paths
- Treat InvalidSetNameError from this function as a 400 (client-supplied), not a server fault
When it happens
Trigger: A symlink inside sets/{name}/inputs/ pointing to a file outside the set directory (realpath resolves through it); on platforms where the inputs dir itself is a symlink and path prefix logic mismatches; virtually unreachable for plain string traversal like "../../etc/passwd" because basename() neutralizes it first.
Common situations: Users symlinking shared image folders into a set's inputs dir instead of copying files; odd mounts or bind mounts making realpath prefixes inconsistent.
Related errors
- Invalid asset path
- data.detail || "Request failed"
- Anthropic API key not found
- Gemini API key not found
- OpenAI API key not found
AI-assisted analysis of abi/screenshot-to-code@d026163f58 (2026-08-14).
Data as JSON: /api/errors/fa33fba15315707f.
Report an issue: GitHub.