T09 · Insecure Skill Coding Practices
- Location
scripts/uninstall.py:137- Finding
Destructive uninstall path lacks an enforced confirmation gate
- Content
View full analysis
Vulnerability Details
File Location:
scripts/uninstall.py, lines 137–147, 230–255, and 290
Vulnerability Type: Destructive credential revocation and state deletion without mandatory confirmation
Risk Level: MediumVulnerable Code
python def _remove_local_state(state_dir: Path) -> None: for name in _STATE_FILES: try: (state_dir / name).unlink(missing_ok=True) except OSError: pass try: state_dir.rmdir() except OSError: passpython if dry_run: result.update({"decision": "disconnected", "revoked": False, "reason": "dry_run"}) return result token = _device_token(state_dir) revoked = False revoke_state = "no_credential" if token is not None: try: status = post_revoke(token, _revoke_url(state_dir)) if status == 200: revoked = True revoke_state = "revoked" elif status == 401: revoke_state = "not_recognized" else: result.update( { "decision": "revoke_retry", "revoked": False, "reason": f"http_{status}", } ) return result except RuntimeError: revoke_state = "unreachable" token = None _remove_local_state(state_dir)python result = uninstall(dry_run=args.dry_run)Technical Analysis
The uninstall command defaults to
dry_run=False. Therefore, directly invoking:text python3 scripts/uninstall.pycan enter a destructive path without an interactive prompt, an explicit confirmation flag, or a confirmation token tied to the current operation.
When the local inventory indicates that no other Beatra Skill remains, the script reads the shared device token, submits it to the Beatra revocation endpoint, and deletes the enumerated fi ...[truncated 1989 chars]
- Remediation
View remediation
Remediation Suggestions
-
Make dry-run behavior the default and require an explicit destructive flag, such as:
text python3 scripts/uninstall.py --confirm-disconnect -
Require interactive confirmation when a terminal is available. The prompt should identify:
- The resolved package path.
- Whether this is considered the final Beatra Skill.
- That the shared device token will be revoked.
- The exact local state directory that will be modified.
-
For non-interactive Agent use, require a short-lived confirmation value generated by a prior dry run and bound to:
- The resolved package path.
- The inventory digest.
- The intended state directory.
- An expiration timestamp.
-
Revalidate the inventory immediately before revocation and deletion so that changes between preview and execution fail safely.
-
Preserve the current conservative behavior for missing, unreadable, or inconsistent inventory and continue avoiding recursive deletion of unknown state.
-
