T09 · Insecure Skill Coding Practices
- Location
do_audit.py:91- Finding
Server-Controlled Arbitrary File Write via Unsanitized Output Filename
- Content
View full analysis
Vulnerability Details
File Location:
do_audit.py, lines 91–94
Vulnerability Type: Path traversal leading to arbitrary file write
Risk Level: HighVulnerable Code
python fname = yr['excel']['filename'] out_path = os.path.join(out_dir, fname) with open(out_path, 'wb') as f: f.write(base64.b64decode(yr['excel']['data']))Technical Analysis
The filename and file contents are taken from the remote API response. The code passes
yr['excel']['filename']directly toos.path.join()without rejecting absolute paths, removing traversal components, resolving the resulting path, or verifying that it remains insideout_dir.os.path.join()does not enforce directory containment. A filename containing../components can escape the designated output directory. On supported platforms, an absolute filename can also cause the preceding output directory to be discarded.The decoded response data is consequently written to a server-selected filesystem location. Exploitation requires control over, or compromise of, the configured HTTPS API endpoint or its response-generation path. TLS reduces network interception risk but does not protect against a compromised or malicious server.
Attack Path
- A threat actor compromises the configured API service or gains control over the response returned for a processing request.
- The user runs the Skill with ordinary brokerage-statement inputs.
- The malicious response reports success and supplies an Excel object such as:
json { "filename": "../../../../home/user/.bashrc", "data": "<Base64-encoded attacker-controlled content>" }- The script joins this filename with
out_dirbut does not enforce containment. base64.b64decode()produces attacker-controlled bytes.open(out_path, 'wb')creates or truncates the selected file and writes those bytes.- If the chosen file is subsequently loaded or executed, such as a shell startup file, the attacker-controlled behavio ...[truncated 804 chars]
- Remediation
View remediation
Remediation Suggestions
Treat all API-provided filenames and file contents as untrusted.
- Reject absolute paths and filenames containing path separators or traversal components.
- Reduce the response filename to a safe basename and preferably generate the local filename independently.
- Resolve both the output directory and destination path, then verify containment before opening the file.
- Restrict expected filename extensions, such as
.xlsx. - Avoid overwriting existing files by default; use exclusive creation or require explicit user confirmation.
- Validate the decoded output format before saving it.
- Apply a maximum decoded-file size to prevent resource exhaustion.
- Consider cryptographically authenticating response metadata if the API architecture supports it.
Example containment pattern:
python base_dir = os.path.realpath(out_dir) fname = os.path.basename(yr['excel']['filename']) if not fname or not fname.lower().endswith('.xlsx'): raise ValueError('Invalid output filename') out_path = os.path.realpath(os.path.join(base_dir, fname)) if os.path.commonpath([base_dir, out_path]) != base_dir: raise ValueError('Output path escapes the selected directory') with open(out_path, 'xb') as f: f.write(base64.b64decode(yr['excel']['data'], validate=True))
