T09 · Insecure Skill Coding Practices
- Location
scripts/init_book.py:13- Finding
Unsanitized project and character names allow path traversal and unintended file access
- Content
View full analysis
2 else "" # Create project root base_dir = Path.home() / ".qclaw" / "workspace" / "novels" / book_name dirs = [ base_dir / "settings" / "characters", base_dir / "outline", base_dir / "chapters", base_dir / "tracker", ] for d in dirs: d.mkdir(parents=True, exist_ok=True) (base_dir / "state.json").write_text( json.dumps(state, ensure_ascii=False, indent=2), encoding="utf-8" ) (base_dir / "tracker" / "foreshadowing.json").write_text( json.dumps(foreshadowing, ensure_ascii=False, indent=2), encoding="utf-8" ) (base_dir / "tracker" / "conflicts.json").write_text( json.dumps(conflicts, ensure_ascii=False, indent=2), encoding="utf-8" ) (base_dir / "tracker" / "style-log.md").write_text( f"# 文风日志 - {book_name}\n\n## 记录\n", encoding="utf-8" ) (base_dir / "settings" / "world.md").write_text( f"# 世界观设定 - {book_name}\n\n", encoding="utf-8" ) (base_dir / "outline" / "arc-outline.md").write_text( f"# 分卷大纲 - {book_name}\n\n", encoding="utf-8" ) ``` `scripts/char_state.py:24-36`: ```python ROOT = Path.home() / ".qclaw" / "workspace" / "novels" def _chars_dir(book): return ROOT / book / "settings" / "characters" def _state_file(book, name): return _chars_dir(book) / name / "state.json" def _bus_file(book): return ROOT / book / "tracker" / "plot_bus.json" ``` `scripts/ncg.py:18-30`: ```python ROOT = Path.home() / ".qclaw" / "workspace" / "novels" def _ncg_file(book): return ROOT / book / "tracker" ...[truncated 3738 chars]- Remediation
View remediation
Path: for part in parts: candidate = Path(part) if ( not part or candidate.is_absolute() or part in {".", ".."} or "/" in part or "\\" in part ): raise ValueError("Invalid path component") result = root.joinpath(*parts).resolve() if not result.is_relative_to(root): raise ValueError("Path escapes the permitted workspace") return result ``` 4. Apply the same validated path helper consistently in every script. 5. Refuse to initialize over an existing project unless the user supplies an explicit overwrite option. 6. Use atomic writes through a temporary file in the validated target directory, followed by `Path.replace()`. 7. Where symbolic links are not required, reject targets or parent directories that are symbolic links. 8. Add tests covering absolute paths, nested traversal, mixed separators, symbolic links, and valid international book names. ]]>
