2026-03-10 15:27:24 +08:00
# Mole Security Audit
2025-12-11 15:10:49 +08:00
2026-03-10 15:27:24 +08:00
This document describes the security-relevant behavior of the current `main` branch. It is intended as a public description of Mole's safety boundaries, destructive-operation controls, release integrity signals, and known limitations.
2026-03-08 15:35:45 +08:00
2026-03-10 15:27:24 +08:00
## Executive Summary
2025-12-11 15:18:04 +08:00
2026-03-10 15:27:24 +08:00
Mole is a local system maintenance tool. Its main risk surface is not remote code execution; it is unintended local damage caused by cleanup, uninstall, optimize, purge, installer cleanup, or other destructive operations.
2025-12-11 15:18:04 +08:00
2026-03-10 15:27:24 +08:00
The project is designed around safety-first defaults:
2025-12-11 15:18:04 +08:00
2026-03-10 15:27:24 +08:00
- destructive paths are validated before deletion
- critical system roots and sensitive user-data categories are protected
- sudo use is bounded and additional restrictions apply when elevated deletion is required
- symlink handling is conservative
- preview, confirmation, timeout, and operation logging are used to make destructive behavior more visible and auditable
2026-02-27 10:07:49 +08:00
2026-03-10 15:27:24 +08:00
Mole prioritizes bounded cleanup over aggressive cleanup. When uncertainty exists, the tool should refuse, skip, or require stronger confirmation instead of widening deletion scope.
The project continues to strengthen:
- release integrity and public security signals
- targeted regression coverage for high-risk paths
- clearer documentation for privilege boundaries and known limitations
## Threat Surface
The highest-risk areas in Mole are:
- direct file and directory deletion
- recursive cleanup across common user and system cache locations
- uninstall flows that combine app removal with remnant cleanup
- project artifact purge for large dependency/build directories
- elevated cleanup paths that require sudo
- release, install, and update trust signals for distributed artifacts
`mo analyze` is intentionally lower-risk than cleanup flows:
- it does not require sudo
- it respects normal user permissions and SIP
- delete actions require explicit confirmation
- deletion routes through Finder Trash behavior rather than direct permanent removal
## Destructive Operation Boundaries
All destructive shell file operations are routed through guarded helpers in `lib/core/file_ops.sh` .
Core controls include:
- `validate_path_for_deletion()` rejects empty paths
- relative paths are rejected
- path traversal segments such as `..` as a path component are rejected
- paths containing control characters are rejected
- raw `find ... -delete` is avoided for security-sensitive cleanup logic
- removal flows use guarded helpers such as `safe_remove()` , `safe_sudo_remove()` , `safe_find_delete()` , and `safe_sudo_find_delete()`
Blocked paths remain protected even with sudo. Examples include:
2026-01-26 15:43:11 +08:00
2026-01-27 10:22:07 +08:00
```text
2026-03-08 15:35:45 +08:00
/
/System
/bin
/sbin
/usr
/etc
/var
/private
/Library/Extensions
2025-12-28 21:30:39 +08:00
```
2026-03-10 15:27:24 +08:00
Some subpaths under otherwise protected roots are explicitly allowlisted for bounded cleanup where the project intentionally supports cache/log maintenance. Examples include:
2025-12-28 21:30:39 +08:00
2026-03-08 15:35:45 +08:00
- `/private/tmp`
- `/private/var/tmp`
- `/private/var/log`
- `/private/var/folders`
- `/private/var/db/diagnostics`
- `/private/var/db/DiagnosticPipeline`
- `/private/var/db/powerlog`
- `/private/var/db/reportmemoryexception`
2025-12-28 21:30:39 +08:00
2026-03-10 15:27:24 +08:00
This design keeps cleanup scoped to known-safe maintenance targets instead of broad root-level deletion patterns.
2025-12-28 21:30:39 +08:00
2026-03-11 11:25:03 +08:00
## Path Protection Reference
### Protected Prefixes (Never Deleted)
```text
/
/System
/bin
/sbin
/usr
/etc
/var
/private
/Library/Extensions
```
### Whitelist Exceptions (Allowlisted for Cleanup)
Some subpaths under protected roots are explicitly allowlisted:
- `/private/tmp`
- `/private/var/tmp`
- `/private/var/log`
- `/private/var/folders`
- `/private/var/db/diagnostics`
- `/private/var/db/DiagnosticPipeline`
- `/private/var/db/powerlog`
- `/private/var/db/reportmemoryexception`
### Protected Categories
In addition to path blocking, these categories are protected:
- Keychains, password managers, credentials
- VPN/proxy tools (Shadowsocks, V2Ray, Clash, Tailscale)
- AI tools (Cursor, Claude, ChatGPT, Ollama)
- Browser history and cookies
- Time Machine data (during active backup)
- `com.apple.*` LaunchAgents/LaunchDaemons
- iCloud-synced `Mobile Documents`
## Implementation Details
All deletion routes through `lib/core/file_ops.sh` :
- `validate_path_for_deletion()` - Empty, relative, traversal checks
- `should_protect_path()` - Prefix and pattern matching
- `safe_remove()` , `safe_find_delete()` , `safe_sudo_remove()` - Guarded operations
See [`journal/2026-03-11-safe-remove-design.md` ](journal/2026-03-11-safe-remove-design.md ) for design rationale.
2026-03-10 15:27:24 +08:00
## Protected Directories and Categories
2025-12-28 21:30:39 +08:00
2026-03-10 15:27:24 +08:00
Mole has explicit protected-path and protected-category logic in addition to root-path blocking.
2025-12-28 21:30:39 +08:00
2026-03-10 15:27:24 +08:00
Protected or conservatively handled categories include:
2025-12-28 21:30:39 +08:00
2026-03-10 15:27:24 +08:00
- system components such as Control Center, System Settings, TCC, Spotlight, Finder, and Dock-related state
- keychains, password-manager data, tokens, credentials, and similar sensitive material
- VPN and proxy tools such as Shadowsocks, V2Ray, Clash, and Tailscale
- AI tools in generic protected-data logic, including Cursor, Claude, ChatGPT, and Ollama
- `~/Library/Messages/Attachments`
- browser history and cookies
- Time Machine data while backup state is active or ambiguous
- `com.apple.*` LaunchAgents and LaunchDaemons
- iCloud-synced `Mobile Documents` data
2025-12-28 21:30:39 +08:00
2026-03-10 15:27:24 +08:00
Project purge also uses conservative heuristics:
2026-01-11 09:26:04 +08:00
2026-03-10 15:27:24 +08:00
- purge targets must be inside configured project boundaries
- direct-child artifact cleanup is only allowed in single-project mode
- recently modified artifacts are treated as recent for 7 days
- nested artifacts are filtered to avoid parent-child over-deletion
- protected vendor/build-output heuristics block ambiguous directories
2026-02-27 10:07:49 +08:00
2026-03-10 15:27:24 +08:00
Developer cleanup also preserves high-value state. Examples intentionally left alone include:
2026-02-27 10:07:49 +08:00
2026-03-10 15:27:24 +08:00
- `~/.cargo/bin`
- `~/.rustup`
- `~/.mix/archives`
- `~/.stack/programs`
2026-01-11 09:26:04 +08:00
2026-03-10 15:27:24 +08:00
## Symlink and Path Traversal Handling
2026-01-11 09:26:04 +08:00
2026-03-10 15:27:24 +08:00
Symlink behavior is intentionally conservative.
2026-02-27 10:07:49 +08:00
2026-03-10 15:27:24 +08:00
- path validation checks symlink targets before deletion
- symlinks pointing at protected system targets are rejected
- `safe_sudo_remove()` refuses to sudo-delete symlinks
- `safe_find_delete()` and `safe_sudo_find_delete()` refuse to scan symlinked base directories
- installer discovery avoids treating symlinked installer files as deletion candidates
- analyzer scanning skips following symlinks to unexpected targets
2026-02-27 10:07:49 +08:00
2026-03-10 15:27:24 +08:00
Path traversal handling is also explicit:
2025-12-28 21:30:39 +08:00
2026-03-10 15:27:24 +08:00
- non-absolute paths are rejected for destructive helpers
- `..` is rejected when it appears as a path component
- legitimate names containing `..` inside a single path element remain allowed to avoid false positives for real application data
2025-12-28 21:30:39 +08:00
2026-03-10 15:27:24 +08:00
## Privilege Escalation and Sudo Boundaries
2026-01-27 20:22:30 +08:00
2026-03-10 15:27:24 +08:00
Mole uses sudo for a subset of system-maintenance paths, but elevated behavior is still bounded by validation and protected-path rules.
2026-01-27 20:22:30 +08:00
2026-03-10 15:27:24 +08:00
Key properties:
2026-01-27 20:22:30 +08:00
2026-03-10 15:27:24 +08:00
- sudo access is explicitly requested instead of assumed
- non-interactive preview remains conservative when sudo is unavailable
- protected roots remain blocked even when sudo is available
- sudo deletion uses the same path validation gate as non-sudo deletion
- sudo cleanup skips or reports denied operations instead of widening scope
- authentication, SIP/MDM, and read-only filesystem failures are classified separately in file-operation results
2026-02-27 10:07:49 +08:00
2026-03-10 15:27:24 +08:00
When sudo is denied or unavailable, Mole prefers skipping privileged cleanup to forcing execution through unsafe fallback behavior.
2026-01-27 20:22:30 +08:00
2026-03-10 15:27:24 +08:00
## Sensitive Data Exclusions
2025-12-28 21:30:39 +08:00
2026-03-10 15:27:24 +08:00
Mole is not intended to aggressively delete high-value user data.
2025-12-28 21:30:39 +08:00
2026-03-10 15:27:24 +08:00
Examples of conservative handling include:
2025-12-28 21:30:39 +08:00
2026-03-10 15:27:24 +08:00
- sensitive app families are excluded from generic orphan cleanup
- orphaned app data waits for inactivity windows before cleanup
- Claude VM orphan cleanup uses a separate stricter rule
- uninstall file lists are decoded and revalidated before removal
- reverse-DNS bundle ID validation is required before LaunchAgent and LaunchDaemon pattern matching
2025-12-29 19:06:04 +08:00
2026-03-10 15:27:24 +08:00
Installed-app detection is broader than a single `/Applications` scan and includes:
2025-12-29 19:06:04 +08:00
2026-03-10 15:27:24 +08:00
- `/Applications`
- `/System/Applications`
- `~/Applications`
- Homebrew Caskroom locations
- Setapp application paths
2025-12-29 19:06:04 +08:00
2026-03-10 15:27:24 +08:00
This reduces the risk of incorrectly classifying active software as orphaned data.
2025-12-29 19:06:04 +08:00
2026-03-10 15:27:24 +08:00
## Dry-Run, Confirmation, and Audit Logging
2025-12-28 21:30:39 +08:00
2026-03-10 15:27:24 +08:00
Mole exposes multiple safety controls before and during destructive actions:
2026-02-27 10:07:49 +08:00
2026-03-10 15:27:24 +08:00
- `--dry-run` previews are available for major destructive commands
- interactive high-risk flows require explicit confirmation before deletion
- purge marks recent projects conservatively and leaves them unselected by default
- analyzer delete uses Finder Trash rather than direct permanent removal
- operation logs are written to `~/.config/mole/operations.log` unless disabled with `MO_NO_OPLOG=1`
- timeouts bound external commands so stalled discovery or uninstall operations do not silently hang the entire flow
2026-02-27 10:07:49 +08:00
2026-03-10 15:27:24 +08:00
Relevant timeout behavior includes:
2026-02-27 10:07:49 +08:00
2026-03-10 15:27:24 +08:00
- orphan and Spotlight checks: 2s
- LaunchServices rebuild during uninstall: bounded 10s and 15s steps
- Homebrew uninstall cask flow: 300s by default, extended for large apps when needed
- project scans and sizing operations: bounded to avoid whole-home stalls
2025-12-28 21:30:39 +08:00
2026-03-10 15:27:24 +08:00
## Release Integrity and Continuous Security Signals
2025-12-28 21:30:39 +08:00
2026-03-10 15:27:24 +08:00
Mole treats release trust as part of its security posture, not just a packaging detail.
2025-12-28 21:30:39 +08:00
2026-03-10 15:27:24 +08:00
Repository-level signals include:
2025-12-28 21:30:39 +08:00
2026-03-10 15:27:24 +08:00
- weekly Dependabot updates for Go modules and GitHub Actions
- CI checks for unsafe `rm -rf` usage patterns and core protection behavior
- targeted tests for path validation, purge boundaries, symlink behavior, dry-run flows, and destructive helpers
- CodeQL scanning for Go and GitHub Actions workflows
- curated changelog-driven release notes with a dedicated `Safety-related changes` section
- published SHA-256 checksums for release assets
- GitHub artifact attestations for release assets
2025-12-28 21:30:39 +08:00
2026-03-10 15:27:24 +08:00
These controls do not eliminate all supply-chain risk, but they make release changes easier to review and verify.
2025-12-28 21:30:39 +08:00
2026-03-10 15:27:24 +08:00
## Testing Coverage
2025-12-28 21:30:39 +08:00
2026-03-10 15:27:24 +08:00
There is no single `tests/security.bats` file. Instead, security-relevant behavior is covered by focused suites, including:
2026-02-21 23:38:41 +08:00
2026-03-10 15:27:24 +08:00
- `tests/core_safe_functions.bats`
2026-02-21 23:38:41 +08:00
- `tests/clean_core.bats`
- `tests/clean_user_core.bats`
- `tests/clean_dev_caches.bats`
- `tests/clean_system_maintenance.bats`
2026-03-08 15:35:45 +08:00
- `tests/clean_apps.bats`
2026-02-27 11:18:53 +08:00
- `tests/purge.bats`
2026-03-10 15:27:24 +08:00
- `tests/installer.bats`
2026-03-08 15:35:45 +08:00
- `tests/optimize.bats`
2026-02-21 23:38:41 +08:00
2026-03-10 15:27:24 +08:00
Key coverage areas include:
2025-12-28 21:30:39 +08:00
2026-03-10 15:27:24 +08:00
- path validation rejects empty, relative, traversal, and system paths
- symlinked directories are rejected for destructive scans
- purge protects shallow or ambiguous paths and filters nested artifacts
- dry-run flows preview actions without applying them
- confirmation flows exist for high-risk interactive operations
2025-12-28 21:30:39 +08:00
2026-03-10 15:27:24 +08:00
## Known Limitations and Future Work
2025-12-28 21:30:39 +08:00
2026-03-10 15:27:24 +08:00
- Cleanup is destructive. Most cleanup and uninstall flows do not provide undo.
- `mo analyze` delete is safer because it uses Trash, but other cleanup flows are permanent once confirmed.
- Generic orphan data waits 30 days before cleanup; this is conservative but heuristic.
- Claude VM orphan cleanup waits 7 days before cleanup; this is also heuristic.
- Time Machine safety windows are hour-based and intentionally conservative.
2026-03-08 15:35:45 +08:00
- Localized app names may still be missed in some heuristic paths, though bundle IDs are preferred where available.
- Users who want immediate removal of app data should use explicit uninstall flows rather than waiting for orphan cleanup.
2026-03-10 15:27:24 +08:00
- Release signing and provenance signals are improving, but downstream package-manager trust also depends on external distribution infrastructure.
- Planned follow-up work includes stronger destructive-command threat modeling, more regression coverage for high-risk paths, and continued hardening of release integrity and disclosure workflow.
For reporting procedures and supported versions, see [SECURITY.md ](SECURITY.md ).