1
0
mirror of https://github.com/tw93/Mole.git synced 2026-02-04 20:19:45 +00:00
Files
Mole/SECURITY_AUDIT.md

5.4 KiB

Mole Security Reference

Version 1.23.2 | 2026-01-26

Recent Fixes

Uninstall audit, Jan 2026:

  • stop_launch_services() now checks bundle_id is valid reverse-DNS before using it in find patterns. This stops glob injection.
  • find_app_files() skips LaunchAgents named after common words like Music or Notes.
  • Added comments explaining why remove_file_list() bypasses TOCTOU checks for symlinks.
  • brew_uninstall_cask() treats exit code 124 as timeout failure, returns immediately.

Other changes:

  • Symlink cleanup in bin/clean.sh goes through safe_remove now
  • Orphaned helper cleanup in lib/clean/apps.sh switched to safe_sudo_remove
  • ByHost pref cleanup checks bundle ID format first

Path Validation

Every deletion goes through lib/core/file_ops.sh. The validate_path_for_deletion() function rejects empty paths, paths with /../ in them, and anything containing control characters like newlines or null bytes.

Blocked paths, even with sudo:

/                    # root
/System              # macOS system
/bin, /sbin, /usr    # binaries
/etc, /var           # config
/Library/Extensions  # kexts
/private             # system private

Some system caches are OK to delete:

  • /System/Library/Caches/com.apple.coresymbolicationd/data
  • /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

See lib/core/file_ops.sh:60-78.

When running with sudo, safe_sudo_recursive_delete() also checks for symlinks. Refuses to follow symlinks pointing to system files.

Cleanup Rules

Orphan detection at lib/clean/apps.sh:orphan_detection():

App data is only considered orphaned if the app itself is gone from all three locations: /Applications, ~/Applications, /System/Applications. On top of that, the data must be untouched for at least 60 days. Adobe, Microsoft, and Google stuff is whitelisted regardless.

Uninstall matching at lib/clean/apps.sh:uninstall_app():

App names need at least 3 characters. Otherwise "Go" would match "Google" and that's bad. Fuzzy matching is off. Receipt scans only look under /Applications and /Library/Application Support, not in shared places like /Library/Frameworks.

Dev tools:

Cache dirs like ~/.cargo/registry/cache or ~/.gradle/caches get cleaned. But ~/.cargo/bin, ~/.mix/archives, ~/.rustup toolchains, ~/.stack/programs stay untouched.

LaunchAgent removal:

Only removed when uninstalling the app that owns them. All com.apple.* items are skipped. Services get stopped via launchctl first. Generic names like Music, Notes, Photos are excluded from the search.

See lib/core/app_protection.sh:find_app_files().

Protected Categories

Category What's protected
System Control Center, System Settings, TCC, /Library/Updates, Spotlight
VPN/Proxy Shadowsocks, V2Ray, Tailscale, Clash
AI Cursor, Claude, ChatGPT, Ollama, LM Studio
Time Machine Checks if backup is running. If status unclear, skips cleanup.
Startup com.apple.* LaunchAgents/Daemons always skipped

See lib/core/app_protection.sh:is_critical_system_component().

Analyzer

mo analyze runs differently:

  • Standard user permissions, no sudo
  • Respects SIP
  • Two keys to delete: press ⌫ first, then Enter. Hard to delete by accident.
  • Files go to Trash via Finder API, not rm

Code at cmd/analyze/*.go.

Timeouts

Operation Timeout Why
Network volume check 5s NFS/SMB/AFP can hang forever
App bundle search 10s mdfind sometimes stalls
SQLite vacuum 20s Skip if Mail/Safari/Messages is open
dyld cache rebuild 180s Skip if done in last 24h

See lib/core/base.sh:run_with_timeout().

User Config

Put paths in ~/.config/mole/whitelist, one per line:

# exact matches only
/Users/me/important-cache
~/Library/Application Support/MyApp

These paths are protected from all operations.

Run mo clean --dry-run or mo optimize --dry-run to preview what would happen without actually doing it.

Testing

Area Coverage
File ops 95%
Cleaning 87%
Optimize 82%
System 90%
Security 100%

180+ test cases total, about 88% coverage.

bats tests/              # run all
bats tests/security.bats # security only

CI runs shellcheck and go vet on every push.

Dependencies

System binaries used, all SIP protected:

Binary For
plutil plist validation
tmutil Time Machine
dscacheutil cache rebuild
diskutil volume info

Go libs in analyze-go:

Lib Version License
bubbletea v0.23+ MIT
lipgloss v0.6+ MIT
gopsutil v3.22+ BSD-3
xxhash v2.2+ BSD-2

Versions are pinned. No CVEs. Binaries built via GitHub Actions.

Limitations

What Impact Workaround
Needs sudo for system caches Annoying first time Docs explain why
60-day wait for orphans Some junk stays longer Use mo uninstall manually
No undo Gone is gone Use dry-run first
English names only Might miss localized apps Falls back to bundle ID

Won't touch:

  • Your documents or media
  • Password managers or keychains
  • Files under /etc
  • Browser history/cookies
  • Git repos