T09 · Insecure Skill Coding Practices
- Location
audio-rename.py:41- Finding
Path Traversal Through Unrestricted Python Rename Destination
- Content
View full analysis
Vulnerability Details
File Location:
audio-rename.py, lines 41-51
Vulnerability Type: Unrestricted destination path / path traversal
Risk Level: Mediumpython # Ensure ext starts with dot if ext and not ext.startswith('.'): ext = '.' + ext elif not ext: ext = '.m4a' # default extension new_filename = f"{new_name}{ext}" new_path = os.path.join(dir_path, new_filename) new_path = get_unique_path(new_path) os.rename(file_path, new_path)Technical Analysis
The
new_nameargument is incorporated into the destination path without validating that it is a simple filename. Values containing../can escape the source directory. Ifnew_nameis absolute,os.path.join(dir_path, new_filename)discardsdir_pathand uses the attacker-supplied absolute destination.The extension added by the implementation limits the final filename but does not prevent relocation into another writable directory. The code also checks destination availability with
os.path.exists()inget_unique_path()before separately callingos.rename(). This creates a time-of-check-to-time-of-use window: another process can create the selected destination after the check, andos.rename()can replace it on platforms where replacement is permitted.Exploitation requires control over the second command-line argument and access to a source file that the process can rename.
Attack Path
- An attacker or untrusted workflow invokes the script with a valid source audio file.
- The attacker supplies a destination name containing traversal components, such as
../../target/location/audio, or an absolute destination such as/tmp/target. - The script appends the source extension and passes the resulting path to
os.path.join(). - The computed destination resolves outside the source file's directory.
os.rename()moves the source file into the unintended location, provided the process has filesyst ...[truncated 850 chars]
- Remediation
View remediation
Remediation Suggestions
- Require
new_nameto be a filename rather than a path. - Reject absolute paths, directory separators,
.and..path components, and embedded null or control characters. - Verify that
os.path.basename(new_name) == new_name. - Construct the destination from the validated basename, resolve its parent directory, and verify that the resolved parent is exactly the resolved source directory.
- If the stated purpose requires ASCII-only names, enforce an allowlist such as
[A-Za-z0-9_-]+. - Replace the check-then-rename sequence with a no-clobber operation or another atomic destination-reservation strategy.
- Catch filesystem exceptions and return a nonzero exit status without leaving ambiguous workflow state.
- Require
