Back to skill

Security audit

Storage Cleanup

Security checks for vulnerabilities and agentic risk

Overview

This storage cleanup skill is purpose-aligned, but its script can delete user and system resources immediately and sometimes with sudo despite documentation implying safer confirmation behavior.

Review before installing or running. Use only `bash scripts/cleanup.sh --dry-run` first, avoid running it without arguments, and skip high-impact categories such as kernels, Docker, snaps, and Homebrew unless you explicitly want those resources removed. The package is not evidence of exfiltration or persistence, but it can cause real data loss or system changes.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/cleanup.sh:10
Finding

Destructive Cleanup Executes by Default Without Confirmation

Content
View full analysis

Vulnerability Details

File Location: scripts/cleanup.sh:10-15, scripts/cleanup.sh:22-28, scripts/cleanup.sh:104-112; conflicting claims in SKILL.md:8-16
Vulnerability Type: Unsafe destructive default and ineffective confirmation control
Risk Level: High

Vulnerable Code

bash
DRY_RUN=false
SKIP_KERNELS=false
SKIP_SNAP=false
SKIP_DOCKER=false
SKIP_BREW=false
AUTO_YES=false
bash
for arg in "$@"; do
  case "$arg" in
    --dry-run)       DRY_RUN=true ;;
    --skip-kernels)  SKIP_KERNELS=true ;;
    --skip-snap)     SKIP_SNAP=true ;;
    --skip-docker)   SKIP_DOCKER=true ;;
    --skip-brew)     SKIP_BREW=true ;;
    --yes|-y)        AUTO_YES=true ;;
bash
do_clean() {
  local desc="$1"
  shift
  if $DRY_RUN; then
    echo "[DRY-RUN] Would: $desc"
  else
    echo "Cleaning: $desc"
    "$@" 2>/dev/null || true
  fi
}

Technical Analysis

The script initializes DRY_RUN to false, so invoking it without arguments enables destructive operations immediately. Although it parses --yes into AUTO_YES, that variable is never consulted before cleanup begins. There is also no interactive confirmation prompt.

This behavior conflicts with the documentation's claims that the Skill is “safe by default” and that dry-run mode protects users from unintended changes. The implementation instead requires users to explicitly request safety with --dry-run.

The generic do_clean function executes every supplied deletion or cleanup command whenever DRY_RUN is false. This includes rm -rf, package cleanup, journal vacuuming, snap removal, Docker pruning, and kernel package removal. Several Linux operations invoke sudo, increasing the affected scope from user-owned files to system resources.

Errors are suppressed through 2>/dev/null || true, which can also conceal partial failures and make it difficult for users to determine exactly which destruct ...[truncated 1717 chars]

Remediation
View remediation

Remediation Suggestions

  1. Make dry-run behavior the default:

    bash
    DRY_RUN=true
    
  2. Require explicit authorization before enabling destructive mode:

    bash
    --yes|-y)
      AUTO_YES=true
      DRY_RUN=false
      ;;
    
  3. If neither --dry-run nor --yes is supplied, show the planned operations and require an interactive confirmation. Abort when standard input is not an interactive terminal.

  4. Check AUTO_YES before the first destructive operation rather than merely parsing it.

  5. Use separate opt-in flags for high-impact categories such as kernels, Docker, Xcode archives, snaps, and system logs. These should not be included in a generic default cleanup.

  6. Avoid blanket error suppression. Log command failures and return a nonzero status when critical cleanup operations fail.

  7. Update SKILL.md so the documented default behavior precisely matches the implementation and clearly identifies operations requiring sudo.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/cleanup.sh:238
Finding

Cleanup Deletes Resources Beyond the Documented Scope

Content
View full analysis

Vulnerability Details

File Location: scripts/cleanup.sh:238-269, scripts/cleanup.sh:343-348; scope descriptions in SKILL.md:50, SKILL.md:62-64
Vulnerability Type: Overbroad destructive file and resource cleanup
Risk Level: Medium

Vulnerable Code

bash
# Xcode Archives (old builds)
ARCHIVES="$HOME/Library/Developer/Xcode/Archives"
if [ -d "$ARCHIVES" ]; then
  size=$(get_dir_bytes "$ARCHIVES")
  if (( size > 104857600 )); then
    echo "Xcode Archives: $(bytes_to_human $size)"
    do_clean "Clear Xcode Archives" rm -rf "$ARCHIVES"/*
  fi
fi

# iOS Device Support
DEVICE_SUPPORT="$HOME/Library/Developer/Xcode/iOS DeviceSupport"
if [ -d "$DEVICE_SUPPORT" ]; then
  size=$(get_dir_bytes "$DEVICE_SUPPORT")
  if (( size > 524288000 )); then
    echo "iOS DeviceSupport: $(bytes_to_human $size)"
    do_clean "Clear iOS DeviceSupport" rm -rf "$DEVICE_SUPPORT"/*
  fi
fi
bash
if ! $SKIP_DOCKER && command -v docker &>/dev/null; then
  section "Docker"
  docker system df 2>/dev/null || true
  do_clean "Prune dangling Docker images and build cache" docker system prune -f
fi

Technical Analysis

The documentation describes Xcode archives and device support as “old” artifacts, but the implementation does not apply an age, version, or usage filter. Once the directory exceeds its size threshold, rm -rf "$ARCHIVES"/* and rm -rf "$DEVICE_SUPPORT"/* remove every non-hidden entry. The threshold determines whether cleanup occurs; it does not restrict which entries are deleted.

The Docker description says the script removes only unreferenced or dangling images and build cache. However, docker system prune -f has a broader scope: it can remove stopped containers, unused networks, dangling images, and unused build cache. Thus, the displayed description understates the actual operation.

Quoting the parent directory variables prevents ordinary shell w ...[truncated 1755 chars]

Remediation
View remediation

Remediation Suggestions

  1. Apply explicit age filters to Xcode archives instead of deleting every entry. For example, enumerate archives older than a documented retention period and show each candidate during dry-run.

  2. Retain recent archives and allow users to configure the retention period. Require a separate explicit flag before removing all archives.

  3. Determine installed or required iOS device-support versions and remove only versions that are demonstrably obsolete. If reliable detection is unavailable, list candidates and require per-version confirmation.

  4. Replace the broad Docker command with narrowly scoped commands consistent with the description, such as separately pruning dangling images and build cache.

  5. If docker system prune remains necessary, accurately disclose that it may remove stopped containers and unused networks, and require a dedicated opt-in flag and confirmation.

  6. Display an exact resource list before deletion and record the result of each operation.

  7. Add tests that compare documented cleanup categories with the actual command scope, including tests proving that recent Xcode archives and stopped Docker containers are retained under default settings.

Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (23)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/cleanup.sh (reported line 130)May include surrounding context.

sh
TRASH_SIZE=$(get_dir_bytes "$TRASH_DIR")
  echo "Trash size: $(bytes_to_human $TRASH_SIZE)"
  if $IS_MAC; then
    do_clean "Empty trash" rm -rf "$HOME/.Trash/"*
  else
    do_clean "Empty trash" rm -rf "$TRASH_DIR/files/"* "$TRASH_DIR/info/"*
  fi

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/cleanup.sh (reported line 132)May include surrounding context.

sh
if $IS_MAC; then
    do_clean "Empty trash" rm -rf "$HOME/.Trash/"*
  else
    do_clean "Empty trash" rm -rf "$TRASH_DIR/files/"* "$TRASH_DIR/info/"*
  fi
else
  echo "Trash is empty"

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/cleanup.sh (reported line 257)May include surrounding context.

sh
size=$(get_dir_bytes "$DERIVED")
    if (( size > 104857600 )); then
      echo "Xcode DerivedData: $(bytes_to_human $size)"
      do_clean "Clear Xcode DerivedData" rm -rf "$DERIVED"/*
    fi
  fi

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/cleanup.sh (reported line 267)May include surrounding context.

sh
size=$(get_dir_bytes "$ARCHIVES")
    if (( size > 104857600 )); then
      echo "Xcode Archives: $(bytes_to_human $size)"
      do_clean "Clear Xcode Archives" rm -rf "$ARCHIVES"/*
    fi
  fi

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/cleanup.sh (reported line 277)May include surrounding context.

sh
size=$(get_dir_bytes "$DEVICE_SUPPORT")
    if (( size > 524288000 )); then
      echo "iOS DeviceSupport: $(bytes_to_human $size)"
      do_clean "Clear iOS DeviceSupport" rm -rf "$DEVICE_SUPPORT"/*
    fi
  fi

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · scripts/cleanup.sh (reported line 287)May include surrounding context.

sh
size=$(get_dir_bytes "$SIMULATORS")
    if (( size > 104857600 )); then
      echo "CoreSimulator Caches: $(bytes_to_human $size)"
      do_clean "Clear CoreSimulator caches" rm -rf "$SIMULATORS"/*
    fi
  fi

Chaining Abuse

High
Category
Tool Misuse
Confidence
89% confidence
Finding

The pipeline into 'xargs sudo apt purge -y' chains auto-discovered package names directly into a privileged destructive command. Because the selection logic for 'OLD_KERNELS' is heuristic and non-empty output is acted on automatically, a misclassification can turn routine cleanup into removal of essential boot packages with system-wide availability impact.

Content

Scanner excerpt · scripts/cleanup.sh (reported line 372)May include surrounding context.

sh
echo "Old kernels found:"
    echo "$OLD_KERNELS"
    if ! $DRY_RUN; then
      echo "$OLD_KERNELS" | xargs sudo apt purge -y 2>&1 || true
      sudo apt autoremove -y 2>&1 || true
    else
      echo "[DRY-RUN] Would purge old kernels"

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · SKILL.md (reported line 74)May include surrounding context.

md
| Flag | Effect |
|------|--------|
| `--dry-run` | Preview cleanup without deleting anything |
| `--yes` / `-y` | Run without confirmation prompts |
| `--skip-kernels` | Don't remove old kernels (Linux) |
| `--skip-snap` | Don't remove disabled snap revisions (Linux) |
| `--skip-docker` | Don't prune Docker |

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · SKILL.md (reported line 86)May include surrounding context.

md
- **Ollama models**: `ollama list` → `ollama rm <unused>`
- **npm global cache**: `npm cache clean --force`
- **Conda envs**: `conda env list` → `conda remove -n <env> --all`
- **Compressed logs**: `sudo find /var/log -name "*.gz" -delete`
- **Flatpak** (Linux): `flatpak uninstall --unused`
- **Time Machine snapshots** (macOS): `tmutil listlocalsnapshots /` → `tmutil deletelocalsnapshots <date>`

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/cleanup.sh (reported line 90)May include surrounding context.

sh
- **Ollama models**: `ollama list` → `ollama rm <unused>`
- **npm global cache**: `npm cache clean --force`
- **Conda envs**: `conda env list` → `conda remove -n <env> --all`
- **Compressed logs**: `sudo find /var/log -name "*.gz" -delete`
- **Flatpak** (Linux): `flatpak uninstall --unused`
- **Time Machine snapshots** (macOS): `tmutil listlocalsnapshots /` → `tmutil deletelocalsnapshots <date>`

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/cleanup.sh (reported line 93)May include surrounding context.

sh
- **Ollama models**: `ollama list` → `ollama rm <unused>`
- **npm global cache**: `npm cache clean --force`
- **Conda envs**: `conda env list` → `conda remove -n <env> --all`
- **Compressed logs**: `sudo find /var/log -name "*.gz" -delete`
- **Flatpak** (Linux): `flatpak uninstall --unused`
- **Time Machine snapshots** (macOS): `tmutil listlocalsnapshots /` → `tmutil deletelocalsnapshots <date>`

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/cleanup.sh (reported line 158)May include surrounding context.

sh
- **Ollama models**: `ollama list` → `ollama rm <unused>`
- **npm global cache**: `npm cache clean --force`
- **Conda envs**: `conda env list` → `conda remove -n <env> --all`
- **Compressed logs**: `sudo find /var/log -name "*.gz" -delete`
- **Flatpak** (Linux): `flatpak uninstall --unused`
- **Time Machine snapshots** (macOS): `tmutil listlocalsnapshots /` → `tmutil deletelocalsnapshots <date>`

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/cleanup.sh (reported line 309)May include surrounding context.

sh
- **Ollama models**: `ollama list` → `ollama rm <unused>`
- **npm global cache**: `npm cache clean --force`
- **Conda envs**: `conda env list` → `conda remove -n <env> --all`
- **Compressed logs**: `sudo find /var/log -name "*.gz" -delete`
- **Flatpak** (Linux): `flatpak uninstall --unused`
- **Time Machine snapshots** (macOS): `tmutil listlocalsnapshots /` → `tmutil deletelocalsnapshots <date>`

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/cleanup.sh (reported line 311)May include surrounding context.

sh
- **Ollama models**: `ollama list` → `ollama rm <unused>`
- **npm global cache**: `npm cache clean --force`
- **Conda envs**: `conda env list` → `conda remove -n <env> --all`
- **Compressed logs**: `sudo find /var/log -name "*.gz" -delete`
- **Flatpak** (Linux): `flatpak uninstall --unused`
- **Time Machine snapshots** (macOS): `tmutil listlocalsnapshots /` → `tmutil deletelocalsnapshots <date>`

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/cleanup.sh (reported line 326)May include surrounding context.

sh
- **Ollama models**: `ollama list` → `ollama rm <unused>`
- **npm global cache**: `npm cache clean --force`
- **Conda envs**: `conda env list` → `conda remove -n <env> --all`
- **Compressed logs**: `sudo find /var/log -name "*.gz" -delete`
- **Flatpak** (Linux): `flatpak uninstall --unused`
- **Time Machine snapshots** (macOS): `tmutil listlocalsnapshots /` → `tmutil deletelocalsnapshots <date>`

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/cleanup.sh (reported line 341)May include surrounding context.

sh
- **Ollama models**: `ollama list` → `ollama rm <unused>`
- **npm global cache**: `npm cache clean --force`
- **Conda envs**: `conda env list` → `conda remove -n <env> --all`
- **Compressed logs**: `sudo find /var/log -name "*.gz" -delete`
- **Flatpak** (Linux): `flatpak uninstall --unused`
- **Time Machine snapshots** (macOS): `tmutil listlocalsnapshots /` → `tmutil deletelocalsnapshots <date>`

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · scripts/cleanup.sh (reported line 39)May include surrounding context.

sh
echo "  --skip-snap     Skip disabled snap revision removal (Linux only)"
      echo "  --skip-docker   Skip Docker cleanup"
      echo "  --skip-brew     Skip Homebrew cleanup (macOS)"
      echo "  --yes, -y       Skip confirmation prompts"
      exit 0 ;;
  esac
done

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
50% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/cleanup.sh (reported line 90)May include surrounding context.

sh
maybe_sudo() {
  if $IS_MAC; then
    # Most macOS cleanup doesn't need sudo
    "$@"
  else
    sudo "$@"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
87% confidence
Finding

This line performs privileged deletion in /tmp using broad filename patterns and 'rm -rf'. On multi-user systems, '/tmp' is a shared namespace, so the script may delete other users' or active processes' temporary directories if they happen to match these patterns and are older than 60 minutes, causing data loss or service disruption.

Content

Scanner excerpt · scripts/cleanup.sh (reported line 162)May include surrounding context.

sh
echo "/tmp size: $(bytes_to_human $TMP_SIZE)"
  if (( TMP_SIZE > 104857600 )); then
    do_clean "Remove stale pip/build dirs from /tmp" bash -c '
      sudo find /tmp -maxdepth 1 -name "pip-*" -type d -mmin +60 -exec rm -rf {} + 2>/dev/null
      sudo find /tmp -maxdepth 1 -name "npm-*" -type d -mmin +60 -exec rm -rf {} + 2>/dev/null
      sudo find /tmp -maxdepth 1 -name "rust_*" -type d -mmin +60 -exec rm -rf {} + 2>/dev/null
    '

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
87% confidence
Finding

This privileged 'find ... -exec rm -rf' removes '/tmp/npm-*' directories solely by age and name. In a shared temp area that can impact unrelated users or applications and can break currently needed build artifacts or sessions.

Content

Scanner excerpt · scripts/cleanup.sh (reported line 163)May include surrounding context.

sh
if (( TMP_SIZE > 104857600 )); then
    do_clean "Remove stale pip/build dirs from /tmp" bash -c '
      sudo find /tmp -maxdepth 1 -name "pip-*" -type d -mmin +60 -exec rm -rf {} + 2>/dev/null
      sudo find /tmp -maxdepth 1 -name "npm-*" -type d -mmin +60 -exec rm -rf {} + 2>/dev/null
      sudo find /tmp -maxdepth 1 -name "rust_*" -type d -mmin +60 -exec rm -rf {} + 2>/dev/null
    '
  fi

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
87% confidence
Finding

This line deletes '/tmp/rust_*' directories as root based only on naming and age. The broad privileged deletion creates a real integrity/availability risk because it can remove legitimate temporary data outside the caller's ownership.

Content

Scanner excerpt · scripts/cleanup.sh (reported line 164)May include surrounding context.

sh
do_clean "Remove stale pip/build dirs from /tmp" bash -c '
      sudo find /tmp -maxdepth 1 -name "pip-*" -type d -mmin +60 -exec rm -rf {} + 2>/dev/null
      sudo find /tmp -maxdepth 1 -name "npm-*" -type d -mmin +60 -exec rm -rf {} + 2>/dev/null
      sudo find /tmp -maxdepth 1 -name "rust_*" -type d -mmin +60 -exec rm -rf {} + 2>/dev/null
    '
  fi
fi

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
88% confidence
Finding

This line pipes package names into 'xargs sudo apt purge -y' without robust validation of the package set. The old-kernel detection heuristic is brittle and can purge packages based on partial string filtering, risking accidental removal of needed kernels and leaving the system unbootable after reboot.

Content

Scanner excerpt · scripts/cleanup.sh (reported line 372)May include surrounding context.

sh
echo "Old kernels found:"
    echo "$OLD_KERNELS"
    if ! $DRY_RUN; then
      echo "$OLD_KERNELS" | xargs sudo apt purge -y 2>&1 || true
      sudo apt autoremove -y 2>&1 || true
    else
      echo "[DRY-RUN] Would purge old kernels"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
83% confidence
Finding

Following the purge with unconditional 'sudo apt autoremove -y' can remove additional dependencies automatically, compounding mistakes from incorrect kernel selection. If the prior package set is wrong, autoremove increases the blast radius and may strip required boot components.

Content

Scanner excerpt · scripts/cleanup.sh (reported line 373)May include surrounding context.

sh
echo "$OLD_KERNELS"
    if ! $DRY_RUN; then
      echo "$OLD_KERNELS" | xargs sudo apt purge -y 2>&1 || true
      sudo apt autoremove -y 2>&1 || true
    else
      echo "[DRY-RUN] Would purge old kernels"
    fi

Static analysis

No suspicious patterns detected.