From c5d923cd4829d94bc33daa155f7ed2ca73d5164a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=90?= Date: Fri, 13 Mar 2026 11:38:37 +0800 Subject: [PATCH] fix(appli-support):using whitelist in application_support clean (#562) * fix(appli-support):using whitelist in application_support clean * fix: harden clash verge app support protection --------- Co-authored-by: Tw93 --- lib/clean/user.sh | 12 +++++++++++- lib/core/app_protection.sh | 4 +++- tests/clean_user_core.bats | 31 +++++++++++++++++++++++++++++++ tests/core_common.bats | 3 +++ 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/lib/clean/user.sh b/lib/clean/user.sh index 60e2af9..86fcf07 100644 --- a/lib/clean/user.sh +++ b/lib/clean/user.sh @@ -860,7 +860,11 @@ clean_application_support_logs() { local app_name_lower app_name_lower=$(echo "$app_name" | LC_ALL=C tr '[:upper:]' '[:lower:]') local is_protected=false - if should_protect_data "$app_name"; then + if is_path_whitelisted "$app_dir" 2> /dev/null; then + is_protected=true + elif should_protect_path "$app_dir" 2> /dev/null; then + is_protected=true + elif should_protect_data "$app_name"; then is_protected=true elif should_protect_data "$app_name_lower"; then is_protected=true @@ -874,6 +878,9 @@ clean_application_support_logs() { local -a start_candidates=("$app_dir/log" "$app_dir/logs" "$app_dir/activitylog" "$app_dir/Cache/Cache_Data" "$app_dir/Crashpad/completed") for candidate in "${start_candidates[@]}"; do if [[ -d "$candidate" ]]; then + if should_protect_path "$candidate" 2> /dev/null || is_path_whitelisted "$candidate" 2> /dev/null; then + continue + fi # Quick count check - skip if too many items to avoid hanging local quick_count quick_count=$(app_support_entry_count_capped "$candidate" 1 101) @@ -901,6 +908,9 @@ clean_application_support_logs() { local candidate_item_count=0 while IFS= read -r -d '' item; do [[ -e "$item" ]] || continue + if should_protect_path "$item" 2> /dev/null || is_path_whitelisted "$item" 2> /dev/null; then + continue + fi item_found=true candidate_item_count=$((candidate_item_count + 1)) if [[ ! -L "$item" && (-f "$item" || -d "$item") ]]; then diff --git a/lib/core/app_protection.sh b/lib/core/app_protection.sh index 144aac4..a37857f 100755 --- a/lib/core/app_protection.sh +++ b/lib/core/app_protection.sh @@ -290,6 +290,8 @@ readonly DATA_PROTECTED_BUNDLES=( "clash.*" "Clash.*" "clash_*" + "*clash-verge*" + "*Clash-Verge*" "clashverge*" "ClashVerge*" "com.nssurge.surge-mac" @@ -694,7 +696,7 @@ should_protect_data() { com.nssurge.* | com.v2ray.* | com.clash.* | ClashX* | Surge* | Shadowrocket* | Quantumult*) return 0 ;; - clash-* | Clash-* | *-clash | *-Clash | clash.* | Clash.* | clash_* | clashverge* | ClashVerge*) + clash-* | Clash-* | *-clash | *-Clash | clash.* | Clash.* | clash_* | *clash-verge* | *Clash-Verge* | clashverge* | ClashVerge*) return 0 ;; com.docker.* | com.getpostman.* | com.insomnia.*) diff --git a/tests/clean_user_core.bats b/tests/clean_user_core.bats index acf3b54..89d226e 100644 --- a/tests/clean_user_core.bats +++ b/tests/clean_user_core.bats @@ -255,6 +255,37 @@ EOF [[ "$output" != *"REMOVE:"* ]] } +@test "clean_application_support_logs skips whitelisted application support directories" { + local support_home="$HOME/support-appsupport-whitelist" + run env HOME="$support_home" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF' +set -euo pipefail +mkdir -p "$HOME" +source "$PROJECT_ROOT/lib/core/common.sh" +source "$PROJECT_ROOT/lib/clean/user.sh" +start_section_spinner() { :; } +stop_section_spinner() { :; } +note_activity() { :; } +safe_remove() { echo "REMOVE:$1"; } +update_progress_if_needed() { return 1; } +should_protect_data() { return 1; } +is_critical_system_component() { return 1; } +WHITELIST_PATTERNS=("$HOME/Library/Application Support/io.github.clash-verge-rev.clash-verge-rev") +files_cleaned=0 +total_size_cleaned=0 +total_items=0 + +mkdir -p "$HOME/Library/Application Support/io.github.clash-verge-rev.clash-verge-rev/logs" +touch "$HOME/Library/Application Support/io.github.clash-verge-rev.clash-verge-rev/logs/runtime.log" + +clean_application_support_logs +test -f "$HOME/Library/Application Support/io.github.clash-verge-rev.clash-verge-rev/logs/runtime.log" +rm -rf "$HOME/Library/Application Support" +EOF + + [ "$status" -eq 0 ] + [[ "$output" != *"REMOVE:"* ]] +} + @test "app_support_entry_count_capped stops at cap without failing under pipefail" { local support_home="$HOME/support-appsupport-cap" run env HOME="$support_home" PROJECT_ROOT="$PROJECT_ROOT" bash --noprofile --norc <<'EOF' diff --git a/tests/core_common.bats b/tests/core_common.bats index 69d0a6f..23afe44 100644 --- a/tests/core_common.bats +++ b/tests/core_common.bats @@ -142,6 +142,9 @@ EOF result=$(HOME="$HOME" bash --noprofile --norc -c "source '$PROJECT_ROOT/lib/core/common.sh'; should_protect_data 'com.clash.app' && echo 'protected' || echo 'not-protected'") [ "$result" = "protected" ] + result=$(HOME="$HOME" bash --noprofile --norc -c "source '$PROJECT_ROOT/lib/core/common.sh'; should_protect_data 'io.github.clash-verge-rev.clash-verge-rev' && echo 'protected' || echo 'not-protected'") + [ "$result" = "protected" ] + result=$(HOME="$HOME" bash --noprofile --norc -c "source '$PROJECT_ROOT/lib/core/common.sh'; should_protect_data 'com.example.RegularApp' && echo 'protected' || echo 'not-protected'") [ "$result" = "not-protected" ] }