T09 · Insecure Skill Coding Practices
- Location
scripts/main.py:169- Finding
Unrestricted Output Path Allows Arbitrary File Overwrite
- Content
View full analysis
Vulnerability Details
File Location:
scripts/main.py:169-172
Vulnerability Type: Unrestricted file write and path traversal
Risk Level: Mediumpython if args.output: with open(args.output, 'w', encoding='utf-8') as f: f.write(output) print(f"Results saved to: {args.output}")Technical Analysis
The application accepts a caller-controlled output path and opens it in write mode without path normalization, workspace-boundary enforcement, traversal checks, symlink validation, or overwrite protection. Python's
open(..., 'w')truncates an existing destination and follows symbolic links.Although
SKILL.mdstates that output should be restricted to the workspace and that../traversal should be prevented, the implementation does not enforce either control.Attack Path
- An attacker or untrusted caller supplies an output argument containing an absolute path or traversal sequence, such as:
bash python scripts/main.py --tp 90 --fn 10 --tn 80 --fp 20 \ --output ../../writable-target - The calculator produces valid JSON output.
- The program passes the attacker-controlled path directly to
open()with modew. - If the process can write to the destination, the existing file is truncated and replaced with calculator output.
- If the selected path is a symbolic link, the linked target may be overwritten as well.
Impact Assessment
The attacker can overwrite or corrupt any file writable by the operating-system account running the Skill. The vulnerability does not independently elevate privileges; its scope is bounded by the process's existing filesystem permissions. Potential consequences include project corruption, configuration replacement, denial of service, and overwriting files outside the intended workspace.
- An attacker or untrusted caller supplies an output argument containing an absolute path or traversal sequence, such as:
- Remediation
View remediation
Remediation Suggestions
- Define a dedicated output directory and resolve both it and the requested destination with
pathlib.Path.resolve(). - Reject destinations that are not descendants of the approved output directory.
- Reject absolute paths when only workspace-relative paths are expected.
- Prevent symlink-based escapes by rejecting symlink components and safely validating the final destination.
- Avoid silently truncating existing files. Use exclusive creation mode (
x) where overwriting is unnecessary, or require explicit overwrite authorization. - Run the Skill with minimal filesystem permissions.
- Catch filesystem exceptions and return concise, sanitized errors.
Example boundary check:
python from pathlib import Path output_root = (Path.cwd() / "output").resolve() output_root.mkdir(parents=True, exist_ok=True) destination = (output_root / args.output).resolve() if output_root not in destination.parents: raise ValueError("Output path must remain inside the output directory") if destination.exists() or destination.is_symlink(): raise ValueError("Refusing to overwrite an existing destination") with destination.open("x", encoding="utf-8") as f: f.write(output)- Define a dedicated output directory and resolve both it and the requested destination with
