T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/cleanup.py:148
- Finding
- Repository Cleanup Can Discard Unique Local Work Based Only on a Matching Remote URL## Vulnerability Details **File Location**: `scripts/cleanup.py`, lines 103–109, 148–155, and 309–313 **Vulnerability Type**: Unsafe destructive repository classification **Risk Level**: High ### Vulnerable Code ```python project_remotes = {} projects_dir = workspace / "projects" if projects_dir.exists(): for pdir in projects_dir.iterdir(): if pdir.is_dir() and (pdir / ".git").exists(): remote = get_git_remote(pdir) if remote: project_remotes[remote] = pdir.name ``` ```python # Duplicate repos elif (item / ".git").exists(): remote = get_git_remote(item) if remote and remote in project_remotes: target = { "path": item, "reason": f"duplicate of projects/{project_remotes[remote]}" } ``` ```python for t in targets: if trash_item(t["path"]): success += 1 if not args.quiet: print(f" Trashed: {t['path'].name}") ``` ### Technical Analysis The implementation treats two Git repositories as duplicates solely because they have the same `origin` URL. A shared remote does not establish that two working trees contain identical data. A root-level repository may contain: - Uncommitted modifications - Untracked or ignored files - Local-only branches - Commits that have not been pushed - A different checked-out revision - Local build artifacts or configuration not present in the other repository The cleaner does not inspect `git status`, compare HEAD revisions, identify untracked files, check branch divergence, or verify file-level equivalence. Once a repository is classified as a duplicate, execution mode passes the entire directory to `trash_item()`. Although the normal workflow defaults to preview mode, documented automation examples invoke `--execute`. The destructive classification can therefore operate without item-by-item confirmation. ### Attack P ...[truncated 1150 chars]
- Remediation
- ## Remediation Suggestions 1. Make repository detection report-only by default, even when general cleanup runs with `--execute`. 2. Require explicit per-repository confirmation or a separate high-risk command-line option before moving any Git repository. 3. Before declaring a repository redundant, verify all of the following: - The working tree and index are clean. - No untracked or ignored user data exists. - HEAD commits are identical. - No local-only branches or tags exist. - No commits are ahead of every configured remote. - Relevant file content is equivalent. 4. Prefer Git-aware archival or a generated review report over automatic removal. 5. Generate a cleanup manifest containing the source path, trash destination, repository state, HEAD commit, and timestamp. 6. Abort repository cleanup if any Git inspection command fails or returns ambiguous results. 7. Add automated tests covering uncommitted changes, untracked files, divergent branches, local-only commits, missing remotes, and repositories with identical remotes but different content.
