T09 · Insecure Skill Coding Practices
- Location
scripts/pipeline.py:443- Finding
Arbitrary File Deletion Through Untrusted Metadata Paths
- Content
View full analysis
Dict[str, Any]: deleted: List[str] = [] kept: List[str] = [] for key in ("wav_path", "transcript_path"): path_value = meta.get(key) if not path_value: continue path = Path(path_value) if mode in {"temp", "all"} and path.exists(): path.unlink() deleted.append(str(path)) elif path.exists(): kept.append(str(path)) video_value = meta.get("local_file") if video_value: video_path = Path(video_value) if mode == "all" and video_path.exists(): video_path.unlink() deleted.append(str(video_path)) elif video_path.exists(): kept.append(str(video_path)) ``` The affected cleanup command loads the paths directly from a user-selected metadata file: ```python def cmd_cleanup(args: argparse.Namespace) -> None: meta = load_metadata(Path(args.metadata)) mode = "all" if args.delete_video else args.mode result = cleanup_from_meta(meta, mode) meta["cleanup"] = result meta["state"] = "cleaned" if mode != "none" else meta.get("state", "prepared") save_metadata(meta, meta.get("bvid", "metadata"), Path(meta["metadata_path"])) print(json.dumps(result, ensure_ascii=False, indent=2)) ``` ### Technical Analysis The cleanup implementation treats the `wav_path`, `transcript_path`, and `local_file` properties in the metadata JSON as trusted filesystem paths. It does not canonicalize these paths or verify that they are located beneath the intended `TEMP_DIR` and `DOWNLOAD_DIR` directories. Because the `--metadata` option accepts an arbitrary JSON fil ...[truncated 1831 chars]- Remediation
View remediation
Path: resolved = candidate.resolve(strict=True) trusted_root = root.resolve(strict=True) if not resolved.is_relative_to(trusted_root): raise RuntimeError(f"Refusing to delete out-of-scope path: {resolved}") if not resolved.is_file(): raise RuntimeError(f"Refusing to delete non-file target: {resolved}") return resolved ``` ]]>
