T09 · Insecure Skill Coding Practices
- Location
scripts/main.py:385- Finding
Unrestricted Output Path Allows Arbitrary File Overwrite
- Content
View full analysis
Vulnerability Details
File Location:
scripts/main.py, lines 336-339 and 385-387
Vulnerability Type: Unrestricted file write and overwrite
Risk Level: MediumVulnerable Code
python parser.add_argument( "--output", "-o", help="Output file path (JSON format)" )python if args.output: with open(args.output, 'w', encoding='utf-8') as f: f.write(json_output)Technical Analysis
The user-controlled
--outputvalue is passed directly toopen()in write mode without path validation or confinement. The implementation does not:- Restrict output to the project workspace or another approved directory.
- Resolve and verify the canonical destination path.
- Reject absolute paths or
../traversal. - detect symbolic-link destinations.
- Require explicit authorization before overwriting an existing file.
- Use exclusive creation or another overwrite-resistant mechanism.
Opening the destination with mode
wimmediately truncates an existing file. Consequently, anyone who can control the command-line arguments can replace any file writable by the skill process.This also conflicts with the security control documented in
SKILL.md, which identifies restriction of output to the workspace as a required safeguard.Attack Path
- An attacker gains control over, or influences, the arguments used to invoke the skill.
- The attacker supplies an absolute path, traversal path, or symlink-backed path through
--output, such as a writable application configuration file. - The script generates its JSON result.
open(args.output, 'w')follows the supplied path and truncates the destination.- The generated JSON replaces the destination file, causing data loss or configuration corruption.
Impact Assessment
The vulnerability grants file-write and file-overwrite capability within the operating-system permissions of the process. It does not independently elevate privileges, but its scope increases if the s ...[truncated 554 chars]
- Remediation
View remediation
Remediation Suggestions
- Define a dedicated output directory under the project workspace.
- Resolve both the approved directory and requested destination with
Path.resolve(). - Verify that the resolved destination remains beneath the approved directory.
- Reject absolute paths, traversal attempts, and symbolic-link destinations.
- Use exclusive creation mode (
x) by default to prevent unintended overwrites. - If overwrite support is required, expose an explicit
--forceoption and validate the destination before replacing it. - Write through a securely created temporary file in the destination directory and use an atomic rename.
- Run the skill with minimum filesystem permissions.
Example containment pattern:
python OUTPUT_DIR = (Path(__file__).parent.parent / "outputs").resolve() OUTPUT_DIR.mkdir(parents=True, exist_ok=True) requested = Path(args.output) if requested.is_absolute(): raise ValueError("Absolute output paths are not permitted") destination = (OUTPUT_DIR / requested).resolve() if OUTPUT_DIR not in destination.parents: raise ValueError("Output path must remain inside the output directory") if destination.exists(): raise FileExistsError("Refusing to overwrite an existing file") with destination.open("x", encoding="utf-8") as f: f.write(json_output)
