T09 · Insecure Skill Coding Practices
- Location
scripts/main.py:112- Finding
Unrestricted User-Controlled Output File Overwrite
- Content
View full analysis
Vulnerability Details
File Location:
scripts/main.py, lines 112–114
Vulnerability Type: Arbitrary file write and overwrite through an unvalidated output path
Risk Level: MediumVulnerable Code
python if args.output: with open(args.output, 'w') as f: f.write(text)Technical Analysis
The
--outputcommand-line argument is passed directly to Python'sopen()function in write mode without path normalization, workspace-boundary enforcement, symlink checks, or overwrite protection.Because mode
'w'creates a missing file and truncates an existing file, anyone able to invoke the skill can select any path writable by the process. Relative traversal paths such as../../targetand unrestricted absolute paths are accepted. This behavior conflicts with the package's documented security requirements to reject../traversal and restrict output to the workspace.The issue does not independently elevate operating-system privileges: file access remains limited to the permissions of the account running the script.
Attack Path
- The attacker identifies a file writable by the skill process.
- The attacker invokes the script with the required parameters and supplies that file through
--output, for example:
bash python scripts/main.py \ --drug example \ --mechanism "blocks target activity" \ --target receptor \ --output ../../target-file- The script accepts the path without validation.
open(args.output, 'w')resolves the traversal path and truncates or creates the selected file.- The generated explanation or animation script is written into that file.
A symlink placed within an otherwise expected output directory could similarly redirect the write unless symlink handling is explicitly enforced.
Impact Assessment
Successful exploitation permits creation or destructive overwrite of files accessible to the process account. Potential consequences include:
- Corruption of project source ...[truncated 496 chars]
- Remediation
View remediation
Remediation Suggestions
- Define a dedicated, trusted output directory rather than accepting unrestricted destinations.
- Resolve both the approved directory and requested destination to canonical absolute paths, then verify that the destination remains beneath the approved directory:
python from pathlib import Path output_root = Path("outputs").resolve() output_root.mkdir(parents=True, exist_ok=True) requested = (output_root / args.output).resolve() if requested == output_root or output_root not in requested.parents: parser.error("Output path must remain within the approved output directory")- Accept a filename or workspace-relative path only; reject absolute paths and explicit traversal components.
- Prevent symlink redirection by checking every relevant path component and using operating-system facilities such as
O_NOFOLLOWwhere available. - Avoid unintended replacement by using exclusive creation mode (
'x') when overwriting is unnecessary. - If replacement is required, write to a securely created temporary file in the same approved directory and atomically replace the destination after validation.
- Apply restrictive file permissions and execute the skill under a least-privileged account.
- Add automated tests covering absolute paths,
../traversal, nested traversal, pre-existing files, and symlink destinations.
