T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/main.py:1077
- Finding
- Unrestricted Output Path Allows Arbitrary File Overwrite## Vulnerability Details **File Location**: `scripts/main.py:1077-1082, 1143-1147` **Vulnerability Type**: Unrestricted filesystem write and arbitrary file overwrite **Risk Level**: Medium ### Vulnerable Code ```python parser.add_argument( "--output", "-o", type=str, default=None, help="输出文件路径 (默认输出到 stdout)" ) ``` ```python if args.output: with open(args.output, "w", encoding="utf-8") as f: f.write(template_content) print(f"✓ 模板已生成: {args.output}") else: print(template_content) ``` ### Technical Analysis The user-controlled `--output` value is passed directly to `open()` in write mode without canonicalization, directory-boundary validation, path-traversal rejection, symlink protection, or overwrite safeguards. Consequently, the program accepts absolute paths and relative paths containing traversal components such as `../`. The `"w"` mode creates a destination that does not exist and truncates an existing destination before writing the generated Markdown. This behavior also conflicts with the security expectations in `SKILL.md`, which identify path validation and workspace-restricted output as required controls. ### Attack Path 1. An attacker or untrusted caller gains influence over the script's command-line arguments. 2. The attacker supplies an absolute path or a traversal path through `--output`, for example: ```bash python scripts/main.py --type general --output ../../writable-target ``` 3. `argparse` accepts the path as an unrestricted string. 4. The script passes it directly to `open(args.output, "w", encoding="utf-8")`. 5. If the process has write permission, the target is created or its existing contents are truncated and replaced with generated Markdown. A writable symlink supplied as the output path may similarly redirect the write to its target because the implementation does not reject or safely handle symlinks. ### Impact Assess ...[truncated 585 chars]
- Remediation
- ## Remediation Suggestions 1. Define an explicit trusted output root rather than accepting unrestricted destinations. 2. Resolve both the trusted root and requested output path to canonical absolute paths and verify that the destination remains inside the trusted root: ```python from pathlib import Path output_root = Path.cwd().resolve() destination = (output_root / args.output).resolve() if destination != output_root and output_root not in destination.parents: parser.error("Output path must remain inside the workspace") ``` 3. Reject absolute user-supplied paths if only workspace-relative paths are required. 4. Reject symlink destinations and inspect existing parent components for unsafe symlinks. Where supported, use operating-system flags that prevent symlink following. 5. Avoid silent truncation. Use exclusive creation mode (`"x"`) by default or require an explicit `--overwrite` option before replacing an existing file. 6. Restrict output file extensions if only Markdown output is expected. 7. Handle filesystem exceptions gracefully without exposing unnecessary environment details. 8. Add tests covering absolute paths, `../` traversal, symlink targets, existing files, and paths outside the configured workspace. 9. Update `SKILL.md` so its security claims accurately reflect the controls implemented in code.
