T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/case_study_scaffold.py:16
- Finding
- Unchecked User-Controlled Output Path Allows Arbitrary File Overwrite## Vulnerability Details **File Location**: `scripts/case_study_scaffold.py`, lines 16–18 **Vulnerability Type**: Unrestricted file overwrite through a user-controlled output path **Risk Level**: Medium ### Vulnerable Code ```python ap.add_argument("--out", default="case_study_scaffold.json") args = ap.parse_args() json.dump(TEMPLATE, open(args.out, "w", encoding="utf-8"), ensure_ascii=False, indent=2) ``` ### Technical Analysis The `--out` argument is passed directly to `open()` in truncating write mode (`"w"`). The implementation does not verify that the destination is inside an approved workspace, does not reject symbolic links, and does not check whether the target already exists. Consequently, invoking the script with an absolute path or traversal-based relative path can replace any file writable by the script's operating-system account. If the output path is a symbolic link, the write follows that link and truncates its target. This behavior also conflicts with the skill's preview-first operating rule in `SKILL.md`. The generated content is a fixed JSON object, so the flaw does not provide arbitrary content control or code execution by itself. Exploitation also requires the attacker to influence the command-line argument used when the helper is invoked. ### Attack Path 1. An attacker influences the value supplied to the helper's `--out` option, potentially through malicious project notes or prompt content that persuades an agent to use a particular path. 2. The agent or user invokes the script, for example: ```bash python3 scripts/case_study_scaffold.py --out /path/to/writable/important-file ``` Alternatively, the attacker selects a path that is a symbolic link to another writable file. 3. The script passes the path directly to `open(..., "w")`. 4. Python creates the file if it does not exist or truncates it if it does. 5. The script replaces the target's contents with the fixed case-study JSON scaffold. ### Impact Assessment The a ...[truncated 635 chars]
- Remediation
- ## Remediation Suggestions 1. Use exclusive creation mode (`"x"`) by default so existing files cannot be silently overwritten: ```python with open(output_path, "x", encoding="utf-8") as output_file: json.dump(TEMPLATE, output_file, ensure_ascii=False, indent=2) ``` 2. Resolve the requested path and require it to remain inside an explicitly approved output directory: ```python from pathlib import Path output_root = Path.cwd().resolve() output_path = (output_root / args.out).resolve() if output_path.parent != output_root: raise ValueError("Output must be created in the approved output directory") ``` If nested output directories are permitted, use a robust containment check such as `output_path.is_relative_to(output_root)` on supported Python versions. 3. Reject symbolic-link destinations and ensure that every existing parent component is trusted. Where race resistance is required, use operating-system facilities such as `os.open()` with `O_CREAT | O_EXCL` and, where supported, `O_NOFOLLOW`. 4. If overwrite functionality is necessary, place it behind an explicit `--force` option and clearly display the resolved destination before writing. 5. Use a context manager to ensure that the file descriptor is closed reliably. 6. Add automated tests covering existing targets, absolute paths, `..` traversal, symbolic links, invalid parent directories, and explicit overwrite behavior. 7. Run the helper with least privilege and avoid invoking it as an administrative or root account.
