1
0
mirror of https://github.com/tw93/Mole.git synced 2026-02-04 15:39:42 +00:00

docs: update SECURITY_AUDIT for receipt processing safety

- Document /private path exceptions for safe cleanup
- Add receipt file filtering details
- Auto-format shell scripts (shellcheck)
This commit is contained in:
Tw93
2026-01-15 21:02:13 +08:00
parent 7dc854cf30
commit 2cecb881a9
4 changed files with 19 additions and 13 deletions

View File

@@ -93,9 +93,14 @@ Even with `sudo`, these paths are **unconditionally blocked**:
/bin, /sbin, /usr # Core binaries
/etc, /var # System configuration
/Library/Extensions # Kernel extensions
/private # System-private directories
```
**Exception:** `/System/Library/Caches/com.apple.coresymbolicationd/data` (safe, rebuildable cache).
**Exceptions:**
- `/System/Library/Caches/com.apple.coresymbolicationd/data` (safe, rebuildable cache)
- `/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`
**Code:** `lib/core/file_ops.sh:60-78`
@@ -161,6 +166,7 @@ For user-selected app removal:
- **Safety Limit:** 3-char minimum (prevents "Go" matching "Google")
- **Disabled:** Fuzzy matching and wildcard expansion for short names.
- **User Confirmation:** Required before deletion.
- **Receipt Scans:** BOM-derived files are limited to safe system prefixes and filtered by `should_protect_path()`.
**Code:** `lib/clean/apps.sh:uninstall_app()`

View File

@@ -13,7 +13,7 @@ _MOLE_CORE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
[[ -z "${MOLE_BASE_LOADED:-}" ]] && source "$_MOLE_CORE_DIR/base.sh"
# Declare WHITELIST_PATTERNS if not already set (used by is_path_whitelisted)
if ! declare -p WHITELIST_PATTERNS &>/dev/null; then
if ! declare -p WHITELIST_PATTERNS &> /dev/null; then
declare -a WHITELIST_PATTERNS=()
fi

View File

@@ -363,7 +363,7 @@ batch_uninstall_applications() {
# Perform uninstallations with per-app progress feedback
local success_count=0 failed_count=0
local brew_apps_removed=0 # Track successful brew uninstalls for autoremove tip
local brew_apps_removed=0 # Track successful brew uninstalls for autoremove tip
local -a failed_items=()
local -a success_items=()
local current_index=0
@@ -573,7 +573,7 @@ batch_uninstall_applications() {
# Auto-run brew autoremove if Homebrew casks were uninstalled
if [[ $brew_apps_removed -gt 0 ]]; then
local autoremove_output removed_count
autoremove_output=$(HOMEBREW_NO_ENV_HINTS=1 brew autoremove 2>/dev/null) || true
autoremove_output=$(HOMEBREW_NO_ENV_HINTS=1 brew autoremove 2> /dev/null) || true
removed_count=$(printf '%s\n' "$autoremove_output" | grep -c "^Uninstalling" || true)
removed_count=${removed_count:-0}
if [[ $removed_count -gt 0 ]]; then

View File

@@ -18,13 +18,13 @@ resolve_path() {
[[ -e "$p" ]] || return 1
# macOS 12.3+ and Linux have realpath
if realpath "$p" 2>/dev/null; then
if realpath "$p" 2> /dev/null; then
return 0
fi
# Fallback: use cd -P to resolve directory, then append basename
local dir base
dir=$(cd -P "$(dirname "$p")" 2>/dev/null && pwd) || return 1
dir=$(cd -P "$(dirname "$p")" 2> /dev/null && pwd) || return 1
base=$(basename "$p")
echo "$dir/$base"
}
@@ -87,9 +87,9 @@ _detect_cask_via_caskroom_search() {
[[ -d "$room" ]] || continue
while IFS= read -r match; do
[[ -n "$match" ]] || continue
token=$(_extract_cask_token_from_path "$match" 2>/dev/null) || continue
token=$(_extract_cask_token_from_path "$match" 2> /dev/null) || continue
[[ -n "$token" ]] && tokens+=("$token")
done < <(find "$room" -maxdepth 3 -name "$app_bundle_name" 2>/dev/null)
done < <(find "$room" -maxdepth 3 -name "$app_bundle_name" 2> /dev/null)
done
# Need at least one token
@@ -101,7 +101,7 @@ _detect_cask_via_caskroom_search() {
# Only succeed if exactly one unique token found and it's installed
if ((${#uniq[@]} == 1)) && [[ -n "${uniq[0]}" ]]; then
HOMEBREW_NO_ENV_HINTS=1 brew list --cask 2>/dev/null | grep -qxF "${uniq[0]}" || return 1
HOMEBREW_NO_ENV_HINTS=1 brew list --cask 2> /dev/null | grep -qxF "${uniq[0]}" || return 1
echo "${uniq[0]}"
return 0
fi
@@ -115,7 +115,7 @@ _detect_cask_via_symlink_check() {
[[ -L "$app_path" ]] || return 1
local target
target=$(readlink "$app_path" 2>/dev/null) || return 1
target=$(readlink "$app_path" 2> /dev/null) || return 1
_extract_cask_token_from_path "$target"
}
@@ -127,10 +127,10 @@ _detect_cask_via_brew_list() {
app_name_lower=$(echo "${app_bundle_name%.app}" | LC_ALL=C tr '[:upper:]' '[:lower:]')
local cask_name
cask_name=$(HOMEBREW_NO_ENV_HINTS=1 brew list --cask 2>/dev/null | grep -Fix "$app_name_lower") || return 1
cask_name=$(HOMEBREW_NO_ENV_HINTS=1 brew list --cask 2> /dev/null | grep -Fix "$app_name_lower") || return 1
# Verify this cask actually owns this app path
HOMEBREW_NO_ENV_HINTS=1 brew info --cask "$cask_name" 2>/dev/null | grep -qF "$app_path" || return 1
HOMEBREW_NO_ENV_HINTS=1 brew info --cask "$cask_name" 2> /dev/null | grep -qF "$app_path" || return 1
echo "$cask_name"
}
@@ -185,7 +185,7 @@ brew_uninstall_cask() {
# Verify removal
local cask_gone=true app_gone=true
HOMEBREW_NO_ENV_HINTS=1 brew list --cask 2>/dev/null | grep -qxF "$cask_name" && cask_gone=false
HOMEBREW_NO_ENV_HINTS=1 brew list --cask 2> /dev/null | grep -qxF "$cask_name" && cask_gone=false
[[ -n "$app_path" && -e "$app_path" ]] && app_gone=false
# Success: uninstall worked and both are gone, or already uninstalled