mirror of
https://github.com/tw93/Mole.git
synced 2026-02-04 17:24:45 +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:
@@ -93,9 +93,14 @@ Even with `sudo`, these paths are **unconditionally blocked**:
|
|||||||
/bin, /sbin, /usr # Core binaries
|
/bin, /sbin, /usr # Core binaries
|
||||||
/etc, /var # System configuration
|
/etc, /var # System configuration
|
||||||
/Library/Extensions # Kernel extensions
|
/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`
|
**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")
|
- **Safety Limit:** 3-char minimum (prevents "Go" matching "Google")
|
||||||
- **Disabled:** Fuzzy matching and wildcard expansion for short names.
|
- **Disabled:** Fuzzy matching and wildcard expansion for short names.
|
||||||
- **User Confirmation:** Required before deletion.
|
- **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()`
|
**Code:** `lib/clean/apps.sh:uninstall_app()`
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ _MOLE_CORE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|||||||
[[ -z "${MOLE_BASE_LOADED:-}" ]] && source "$_MOLE_CORE_DIR/base.sh"
|
[[ -z "${MOLE_BASE_LOADED:-}" ]] && source "$_MOLE_CORE_DIR/base.sh"
|
||||||
|
|
||||||
# Declare WHITELIST_PATTERNS if not already set (used by is_path_whitelisted)
|
# 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=()
|
declare -a WHITELIST_PATTERNS=()
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -363,7 +363,7 @@ batch_uninstall_applications() {
|
|||||||
|
|
||||||
# Perform uninstallations with per-app progress feedback
|
# Perform uninstallations with per-app progress feedback
|
||||||
local success_count=0 failed_count=0
|
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 failed_items=()
|
||||||
local -a success_items=()
|
local -a success_items=()
|
||||||
local current_index=0
|
local current_index=0
|
||||||
@@ -573,7 +573,7 @@ batch_uninstall_applications() {
|
|||||||
# Auto-run brew autoremove if Homebrew casks were uninstalled
|
# Auto-run brew autoremove if Homebrew casks were uninstalled
|
||||||
if [[ $brew_apps_removed -gt 0 ]]; then
|
if [[ $brew_apps_removed -gt 0 ]]; then
|
||||||
local autoremove_output removed_count
|
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=$(printf '%s\n' "$autoremove_output" | grep -c "^Uninstalling" || true)
|
||||||
removed_count=${removed_count:-0}
|
removed_count=${removed_count:-0}
|
||||||
if [[ $removed_count -gt 0 ]]; then
|
if [[ $removed_count -gt 0 ]]; then
|
||||||
|
|||||||
@@ -18,13 +18,13 @@ resolve_path() {
|
|||||||
[[ -e "$p" ]] || return 1
|
[[ -e "$p" ]] || return 1
|
||||||
|
|
||||||
# macOS 12.3+ and Linux have realpath
|
# macOS 12.3+ and Linux have realpath
|
||||||
if realpath "$p" 2>/dev/null; then
|
if realpath "$p" 2> /dev/null; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Fallback: use cd -P to resolve directory, then append basename
|
# Fallback: use cd -P to resolve directory, then append basename
|
||||||
local dir base
|
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")
|
base=$(basename "$p")
|
||||||
echo "$dir/$base"
|
echo "$dir/$base"
|
||||||
}
|
}
|
||||||
@@ -87,9 +87,9 @@ _detect_cask_via_caskroom_search() {
|
|||||||
[[ -d "$room" ]] || continue
|
[[ -d "$room" ]] || continue
|
||||||
while IFS= read -r match; do
|
while IFS= read -r match; do
|
||||||
[[ -n "$match" ]] || continue
|
[[ -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")
|
[[ -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
|
done
|
||||||
|
|
||||||
# Need at least one token
|
# 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
|
# Only succeed if exactly one unique token found and it's installed
|
||||||
if ((${#uniq[@]} == 1)) && [[ -n "${uniq[0]}" ]]; then
|
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]}"
|
echo "${uniq[0]}"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
@@ -115,7 +115,7 @@ _detect_cask_via_symlink_check() {
|
|||||||
[[ -L "$app_path" ]] || return 1
|
[[ -L "$app_path" ]] || return 1
|
||||||
|
|
||||||
local target
|
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"
|
_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:]')
|
app_name_lower=$(echo "${app_bundle_name%.app}" | LC_ALL=C tr '[:upper:]' '[:lower:]')
|
||||||
|
|
||||||
local cask_name
|
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
|
# 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"
|
echo "$cask_name"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,7 +185,7 @@ brew_uninstall_cask() {
|
|||||||
|
|
||||||
# Verify removal
|
# Verify removal
|
||||||
local cask_gone=true app_gone=true
|
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
|
[[ -n "$app_path" && -e "$app_path" ]] && app_gone=false
|
||||||
|
|
||||||
# Success: uninstall worked and both are gone, or already uninstalled
|
# Success: uninstall worked and both are gone, or already uninstalled
|
||||||
|
|||||||
Reference in New Issue
Block a user