[Security] Fix CodeQL alert #29: Uncontrolled data used in path expression#97
[Security] Fix CodeQL alert #29: Uncontrolled data used in path expression#97colin-d-fried wants to merge 1 commit into
Conversation
| with open(file_name, 'r') as f: | ||
| base_dir = os.path.realpath('/var/www/files/') | ||
| safe_path = os.path.realpath(os.path.join(base_dir, file_name)) | ||
| if not safe_path.startswith(base_dir): |
There was a problem hiding this comment.
🔴 Path traversal bypass via startswith check without trailing separator
os.path.realpath('/var/www/files/') strips the trailing slash, so base_dir is /var/www/files. The check safe_path.startswith(base_dir) can be bypassed by accessing sibling directories whose names share the same prefix (e.g., /var/www/files_secret/). For example, filename=../files_secret/passwd resolves to /var/www/files_secret/passwd, which passes the startswith('/var/www/files') check, allowing reads outside the intended directory.
Example bypass
GET /read?filename=../files_secret/sensitive.txt
base_dir=/var/www/filessafe_path=os.path.realpath('/var/www/files/../files_secret/sensitive.txt')=/var/www/files_secret/sensitive.txt'/var/www/files_secret/sensitive.txt'.startswith('/var/www/files')→True→ access granted
| if not safe_path.startswith(base_dir): | |
| if not safe_path.startswith(base_dir + os.sep): |
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| with open(file_name, 'r') as f: | ||
| base_dir = os.path.realpath('/var/www/files/') | ||
| safe_path = os.path.realpath(os.path.join(base_dir, file_name)) | ||
| if not safe_path.startswith(base_dir): |
There was a problem hiding this comment.
Path traversal fix bypassable via sibling directory prefix
High Severity
os.path.realpath strips the trailing slash from '/var/www/files/', so base_dir becomes '/var/www/files'. The startswith check then incorrectly permits access to sibling directories with a common prefix (e.g., /var/www/files_secret/), because '/var/www/files_secret/foo'.startswith('/var/www/files') is True. The check needs to compare against base_dir + os.sep to ensure the resolved path is actually within the intended directory.


Summary
Fixes CodeQL alert #29: Uncontrolled data used in path expression
vulnerable_path_traversal.pyFix Applied
See the diff for the specific secure coding change applied.
Fixes #31
Note
Medium Risk
Adds path canonicalization and base-directory enforcement for user-supplied filenames; low code churn but touches file-system access where mistakes could still allow bypasses or block legitimate files.
Overview
Hardens the
/readendpoint invulnerable_path_traversal.pyby resolving the requestedfilenameagainst a fixed base directory and denying requests whose real path escapes that directory.This replaces direct
open(file_name)withrealpath-based validation and reads from the validatedsafe_path, returning403on traversal attempts.Written by Cursor Bugbot for commit 935aa5d. This will update automatically on new commits. Configure here.