T09 · Insecure Skill Coding Practices
- Location
scripts/convert_book.py:738- Finding
Path Traversal Through an Unvalidated Book Identifier
- Content
View full analysis
None: fields = [ "candidate_id", "book_id", "node_key", "original", "suggestion", "context", "decision", "reviewer", ] path.parent.mkdir(parents=True, exist_ok=True) with path.open("w", encoding="utf-8", newline="") as handle: writer = csv.DictWriter( handle, fieldnames=fields, delimiter="\t", lineterminator="\n", ) writer.writeheader() writer.writerows(rows) ``` ### Technical Analysis The `--book-id` command-line value is accepted without character or path validation and is interpolated directly into output filenames. Python's `pathlib` does not confine the resulting path to `args.output_dir`. A value containing traversal components, such as `../../target`, causes the generated ledger and canonical JSON paths to resolve outside the int ...[truncated 2426 chars]- Remediation
View remediation
Path: resolved_root = root.resolve() destination = (resolved_root / filename).resolve() if not destination.is_relative_to(resolved_root): raise ValueError(f"output path escapes output directory: {destination}") return destination ``` Use this helper for both destinations: ```python ledger_path = confined_path( args.output_dir, f"{args.book_id}_ocr-review.tsv", ) canonical = confined_path( args.output_dir, f"{args.book_id}_tree.json", ) ``` 4. Where supported, account for symlink races by opening files relative to a trusted directory descriptor and using operating-system protections such as `O_NOFOLLOW`. At minimum, reject symlinked output directories or destination files before replacement. 5. Avoid creating parent directories from attacker-derived paths. Create the approved output directory once, then require all generated files to be direct children or explicitly validated descendants. 6. Add regression tests covering: - `../` and nested traversal sequences. - Absolute POSIX paths. - Windows drive and UNC paths. - Forward and backward separators. - NUL and control characters. - Symlinked ...[truncated 186 chars]
