Path traversal in a file-serving route
Part of Security, which counts for 30% of the overall score. When this check fires it deducts 15 points from that category, once per scan, no matter how many places it turns up.
What it detects
A path built with an f-string interpolation is handed directly to open() or FileResponse(), with no visible '..' check, secure_filename(), or resolve()/is_relative_to() guard nearby. A request for a value like '../../etc/passwd' reads whatever file that traversed path resolves to.
Why it matters
Building a file path by interpolating a request-controlled value into an f-string and handing it to open() or FileResponse() is a textbook path traversal: a value like '../../etc/passwd' or an absolute path navigates straight out of the intended directory. Since the route exists specifically to serve files by name, this is usually reachable with nothing more than a normal-looking GET request.
How to fix it
Resolve the requested path against the intended base directory and verify the result is still inside it before opening it: base = Path(UPLOAD_DIR).resolve(); target = (base / filename).resolve(); if not target.is_relative_to(base): raise HTTPException(400). Reject filenames containing '..' or a leading '/' as an extra layer, and prefer looking the file up by an opaque ID or a sanitized name (werkzeug's secure_filename or an equivalent) rather than trusting the raw client-supplied string.
The paid report includes a ready-to-paste prompt for your AI coding agent for every check it finds, pointed at the exact findings from your scan. See pricing
Does your repo trip this check?
Paste a GitHub URL or drop a project folder. Scans run in your browser and take seconds.
Scan your repo