Skip to content

[Security] Fix CodeQL alert #28: Uncontrolled data used in path expression#96

Open
colin-d-fried wants to merge 1 commit into
mainfrom
security/codeql-28-path-traversal-download-fix
Open

[Security] Fix CodeQL alert #28: Uncontrolled data used in path expression#96
colin-d-fried wants to merge 1 commit into
mainfrom
security/codeql-28-path-traversal-download-fix

Conversation

@colin-d-fried
Copy link
Copy Markdown
Owner

@colin-d-fried colin-d-fried commented Mar 26, 2026

Summary

Fixes CodeQL alert #28: Uncontrolled data used in path expression

Field Value
Severity high
File vulnerable_path_traversal.py
CWE CWE-022
Alert CodeQL Alert #28

Fix Applied

See the diff for the specific secure coding change applied.

Fixes #30


Open with Devin

Note

Low Risk
Low-risk, localized security hardening in download_file that changes path resolution and may reject previously-accepted (but unsafe) inputs.

Overview
Hardens the /download endpoint in vulnerable_path_traversal.py against path traversal by resolving the requested filename with os.path.realpath and enforcing that the resulting path stays under the /var/www/uploads/ base directory.

Requests that resolve outside the allowed directory now return 403 Access denied instead of attempting to send_file the path.

Written by Cursor Bugbot for commit cde6d93. This will update automatically on new commits. Configure here.

Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

View 2 additional findings in Devin Review.

Open in Devin Review

file_path = os.path.join('/var/www/uploads/', filename)
base_dir = '/var/www/uploads/'
file_path = os.path.realpath(os.path.join(base_dir, filename))
if not file_path.startswith(os.path.realpath(base_dir)):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Path traversal fix is bypassable due to missing trailing separator in startswith check

The startswith check on line 12 is vulnerable to a directory-prefix bypass. os.path.realpath('/var/www/uploads/') strips the trailing slash, returning /var/www/uploads. An attacker can supply filename=../uploads_evil/secret.txt, which resolves to /var/www/uploads_evil/secret.txt. This passes the startswith('/var/www/uploads') check because the string /var/www/uploads_evil/... does start with /var/www/uploads. The fix must append os.sep to the resolved base directory to ensure only true children of the base directory are matched.

Suggested change
if not file_path.startswith(os.path.realpath(base_dir)):
if not file_path.startswith(os.path.realpath(base_dir) + os.sep):
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

file_path = os.path.join('/var/www/uploads/', filename)
base_dir = '/var/www/uploads/'
file_path = os.path.realpath(os.path.join(base_dir, filename))
if not file_path.startswith(os.path.realpath(base_dir)):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Path traversal check bypassable via sibling directory names

High Severity

The startswith check is bypassable because os.path.realpath(base_dir) strips the trailing slash from /var/www/uploads/, producing /var/www/uploads. A sibling directory like /var/www/uploads_evil/ would also match startswith('/var/www/uploads'), allowing access to files outside the intended directory. The check needs to compare against the resolved base path with a trailing os.sep appended.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CodeQL #28] Uncontrolled data used in path expression

1 participant