T09 · Insecure Skill Coding Practices
- Location
scripts/github_safe_sync.py:234- Finding
Arbitrary Backup Prefix Can Cause Broad Repository Branch Deletion
- Content
View full analysis
int: token = get_token() repo_path = f"/repos/{args.owner}/{args.repo}" branches = [ item["name"] for item in paginate(f"{repo_path}/branches", token) if item["name"].startswith(args.backup_prefix) ] deleted: list[str] = [] for name in branches[: args.limit]: if args.dry_run: deleted.append(name) continue encoded = urllib.parse.quote(f"heads/{name}", safe="") api_request(f"{repo_path}/git/refs/{encoded}", token, method="DELETE") deleted.append(name) print(json.dumps({"matched_count": len(branches), "processed_count": len(deleted), "branches": deleted}, ensure_ascii=False, indent=2)) return 0 ``` ```python delete_backups = sub.add_parser("delete-backups", help="Delete backup/* branches.") delete_backups.add_argument("--owner", required=True) delete_backups.add_argument("--repo", required=True) delete_backups.add_argument("--backup-prefix", default="backup/") delete_backups.add_argument("--limit", type=int, default=1000) delete_backups.add_argument("--dry-run", action="store_true") delete_backups.set_defaults(func=cmd_delete_backups) ``` ### Technical Analysis The `delete-backups` command is documented as deleting branches under the `backup/` namespace, but the namespace is controlled by the unrestricted `--backup-prefix` argument. The code selects branches solely through: ```python item["name"].startswith(args.backup_prefix) ``` An empty string is a valid command-line value and every branch name starts with an empty string. Consequently, passing `--backup-prefix ""` causes all enumerated branches to match. An overly broad value can s ...[truncated 2211 chars]- Remediation
View remediation
