T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/genie.py:991
- Finding
- Snapshot deletion bypasses the documented user-confirmation gate## Vulnerability Details **File Location**: `scripts/genie.py:991-1023`, invoked from `scripts/genie.py:1770-1774` and `scripts/genie.py:1926-1932` **Vulnerability Type**: Destructive operation without code-enforced confirmation **Risk Level**: High ### Technical Analysis The cleanup implementation automatically deletes older rollback snapshots when their age exceeds the configured threshold: ```python def clean_snapshots(snapshots_path, max_age_days, dry_run): result = {"action": "snapshots", "tier": 1, "files": 0, "bytes_freed": 0, "errors": []} if not os.path.isdir(snapshots_path): return result # Find the most recent snapshot (by oldest mtime inside dir) — always preserved entries = [] for entry in os.listdir(snapshots_path): path = os.path.join(snapshots_path, entry) if not os.path.isdir(path): continue oldest = oldest_mtime_in_dir(path) entries.append((oldest, entry, path)) if not entries: return result # Skip the most recent snapshot (highest mtime = youngest) entries.sort(key=lambda x: x[0], reverse=True) most_recent_path = entries[0][2] result["skipped_most_recent"] = os.path.basename(most_recent_path) for oldest, entry, path in entries: if path == most_recent_path: continue snap_age = (datetime.datetime.now().timestamp() - oldest) / 86400 if snap_age > max_age_days: size = du(path) result["files"] += 1 result["bytes_freed"] += size if not dry_run: try: shutil.rmtree(path) ``` The normal cleanup workflow invokes this operation unconditionally: ```python def clean(cfg): tier_limit = int(cfg.get("tier_limit", 3)) results = [] results.append(clean_snapshots( cfg["snapshots_path"], cfg["snapshot_max_age_days"], ...[truncated 1939 chars]
- Remediation
- ## Remediation Suggestions - Default snapshot handling to report-only or dry-run mode. - Require a dedicated flag such as `--confirm-snapshot-deletion` before any snapshot can be removed. - Bind confirmation to the exact snapshot paths displayed during assessment, preventing configuration changes between assessment and deletion from expanding the approved scope. - If emergency deletion is supported, verify the documented emergency condition in code, such as 100% root-filesystem utilization, and clearly record that the emergency bypass was used. - Reject non-interactive snapshot deletion unless a machine-verifiable approval token or explicit automation policy is supplied. - Log each deleted path, size, timestamp, and confirmation mechanism instead of reporting only aggregate reclaimed space. - Preserve the existing newest-snapshot protection and add regression tests proving that `--clean` alone cannot delete snapshots.
