You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+13-1Lines changed: 13 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -17,11 +17,23 @@ All notable changes to DeepPurge will be documented in this file.
17
17
-**Screen-reader narration** — `AutomationProperties.Name` and `.HelpText` on all v0.9 SYSTEM TOOLS panels (drivers, startup impact, shortcuts, duplicates, winapp2, repair, schedule, install monitor, about).
18
18
-**Localization infrastructure** — `Properties/Resources.resx` with top 20 UI strings and a strongly-typed `Resources.Designer.cs` accessor. Ready for Crowdin submission.
19
19
20
+
### Security hardening (research round 2)
21
+
-**CVE-2025-30399 mitigation** — `TargetLatestRuntimePatch` enabled via `Directory.Build.props` to pin .NET runtime ≥8.0.17.
22
+
-**DuplicateFinder thread-safety** — replaced `Dictionary` with `ConcurrentDictionary` for hash cache to prevent data corruption under concurrent scans.
23
+
-**Symlink/junction traversal guards** — all recursive deletion paths in FileLeftoverScanner, JunkFilesCleaner, and EvidenceRemover now check `FileAttributes.ReparsePoint` before traversal. `GetDirectorySize` uses `EnumerationOptions.AttributesToSkip`.
24
+
-**Registry symlink detection** — `SafetyGuard.IsRegistrySymlink()` checks for `REG_LINK` class before any registry write/delete in UninstallEngine. Prevents TOCTOU privilege escalation via registry symbolic links.
25
+
-**NuGet supply chain hardening** — `packages.lock.json` generated for all projects, CI uses `--locked-mode`, NuGet audit enabled at `moderate` level, package source mapping in `NuGet.Config`.
26
+
-**Silent catch logging** — 22 empty `catch { }` blocks in RegistryLeftoverScanner replaced with `Log.Warn()` calls for field debugging.
27
+
-**ManagementObject disposal** — WMI `ManagementObject` instances in SystemRestoreManager and SecureDelete now properly disposed via `using`.
28
+
-**Always-keep protection** — `ProtectedPrograms` persisted list excludes marked programs from batch uninstall. `IsProtected` flag on `InstalledProgram`.
29
+
-**External signature loading** — `LeftoverSignatureDb` now loads `*.signatures.json` files from `DataPaths.Cleaners` alongside the embedded database for community contributions.
30
+
-**Toast notification migration** — replaced deprecated `Microsoft.Toolkit.Uwp.Notifications` with direct WinRT `Windows.UI.Notifications` API. Removes transitive `System.Drawing.Common` 4.7.0 vulnerability.
31
+
20
32
### Changed
21
33
- TFM updated from `net8.0-windows` to `net8.0-windows10.0.17763.0` across all 4 projects to enable WinRT toast notification APIs.
22
34
23
35
### Dependencies
24
-
-New: `Microsoft.Toolkit.Uwp.Notifications 7.1.3` — Windows 10/11 toast notifications.
36
+
-Removed: `Microsoft.Toolkit.Uwp.Notifications 7.1.3` — deprecated, replaced with WinRT API.
Acceptance: Build succeeds on net10.0, all tests pass, ViewModels use `[ObservableProperty] public partial` syntax.
22
22
Complexity: M
23
23
24
24
-[ ] P1 — **CsWin32 type-safe PInvoke**
@@ -42,10 +42,24 @@ Blocked items live in `Roadmap_Blocked.md`.
42
42
Acceptance: User clicks "Hunter Mode" → overlay appears → drag crosshair onto any window → program identified → jump to its entry in the Programs panel.
-[ ] P2 — **Mutation testing on safety-critical code**
48
-
Why: 111 tests for 15.8k LOC is thin. SafetyGuard and deletion logic are safety-critical — need verification that tests actually catch regressions.
62
+
Why: 116 tests for ~14k LOC is thin. SafetyGuard and deletion logic are safety-critical — need verification that tests actually catch regressions.
49
63
Evidence: Stryker.NET 4.14.2; mutation testing best practice for safety-critical paths.
50
64
Touches: `tests/`, `.github/workflows/build.yml`
51
65
Acceptance: Stryker runs in CI on `SafetyGuard.cs`, `SecureDelete.cs`, `UninstallEngine.cs`. Mutation score >80% on these files.
@@ -65,6 +79,13 @@ Blocked items live in `Roadmap_Blocked.md`.
65
79
Acceptance: New sidebar panel with checkboxes for ~15 removable Windows components. Each shows current size. Delete through SafetyGuard with dry-run support.
66
80
Complexity: S
67
81
82
+
-[ ] P2 — **winget COM API migration**
83
+
Why: `winget list --output json` is not a supported CLI option. The `Microsoft.Management.Deployment` COM API is the official programmatic interface.
Why: `_cache` dictionary at `Core/FileSystem/DuplicateFinder.cs:41` is accessed without synchronization. Concurrent `FindAsync` calls corrupt the cache.
104
-
Evidence: Code review — `Dictionary<string, HashCacheEntry>` with no lock around reads/writes in TryGetCachedHead, TryGetCachedFull, UpdateCache.
105
-
Touches: `Core/FileSystem/DuplicateFinder.cs`
106
-
Acceptance: Replace `Dictionary` with `ConcurrentDictionary` or add lock around all cache access. Verify with concurrent scan test.
107
-
Complexity: S
108
-
109
-
-[ ] P0 — **Symlink/junction traversal guard in deletion paths**
110
-
Why: File deletion in FileLeftoverScanner, JunkFilesCleaner, EvidenceRemover does not check for reparse points before recursive deletion. BleachBit shipped a CVE-class fix for this exact pattern. DuplicateFinder.SafeEnumerate already has the guard but other scanners don't.
Acceptance: All recursive directory deletion checks `FileAttributes.ReparsePoint` before traversal. Add test with a junction-loop directory structure.
114
-
Complexity: S
115
-
116
-
-[ ] P0 — **Registry symlink detection before writes**
117
-
Why: Elevated process writes to enumerated registry keys without checking for symlinks. Unprivileged attacker can redirect writes to critical system keys via registry symbolic links. CVE-2025-6231 and CVE-2026-20815 exploited this exact pattern.
118
-
Evidence: Security research — registry TOCTOU privilege escalation; Project Zero Windows Administrator Protection bypass.
Acceptance: Before any registry write/delete, verify key is not a symlink (REG_LINK class check). Fail-closed: if check fails, skip the key and log warning.
121
-
Complexity: S
122
-
123
-
-[ ] P0 — **NuGet supply chain hardening**
124
-
Why: No lock file, no audit, no package source mapping. Dependency confusion and typosquatting attacks possible.
Why: Current 50 profiles cover common apps but benchmark accuracy requires broader coverage. Target: ≥85% accuracy (≤61 leftovers out of 406 artifacts) to reach top-3 in Uninstalr benchmark.
134
-
Evidence: Uninstalr 2026 benchmark — HiBit 90%, Total Uninstall 86%; Revo Logs Database covers 12.5k programs. Also fix: duplicate Spotify entry in current DB.
Touches: New `Core/Packages/PortableAppScanner.cs`, `Core/Packages/PackageManagerScanner.cs`
143
-
Acceptance: Scan common portable locations (Desktop, Downloads, USB roots, PortableApps.com folder) for executables without matching registry entries. Show as "Portable" source in program list.
Why: .NET 9 STS ends Nov 2026 (too soon). .NET 10 is LTS through Nov 2028. CommunityToolkit.Mvvm 8.4.2 partial properties require .NET 9+ SDK but target any runtime. Includes all .NET 9 benefits plus WPF improvements.
Touches: All 4 `.csproj` files — TFM `net10.0-windows10.0.17763.0`. Review P/Invoke DLL loading paths for single-file compatibility.
150
-
Acceptance: Build succeeds on net10.0, all tests pass. Note: this supersedes the existing ".NET 9" ROADMAP item — implementer should do .NET 10 directly.
151
-
Complexity: M
152
-
153
-
-[ ] P1 — **Migrate toast notifications from deprecated package**
154
-
Why: `Microsoft.Toolkit.Uwp.Notifications` 7.1.3 is archived/unmaintained. No security patches. Windows App SDK `AppNotificationManager` is the supported replacement.
155
-
Evidence: NuGet package status (archived); Microsoft migration guidance.
Acceptance: Toast notifications work on Windows 10 1809+ and Windows 11. Remove `Microsoft.Toolkit.Uwp.Notifications` NuGet reference.
158
-
Complexity: S
159
-
160
-
### P2 — Reliability + developer experience
161
-
162
-
-[ ] P2 — **Add logging to silent catch blocks in RegistryLeftoverScanner**
163
-
Why: 16+ `catch { }` blocks with no logging make field debugging impossible. 88 total silent catches across Core.
164
-
Evidence: Code review — `Core/Registry/RegistryLeftoverScanner.cs` has the highest density.
165
-
Touches: `Core/Registry/RegistryLeftoverScanner.cs`, other Core files with silent catches
166
-
Acceptance: All catch blocks in RegistryLeftoverScanner call `Log.Warn()` with the exception message. Other high-density files (FileLeftoverScanner) follow suit.
167
-
Complexity: S
168
-
169
-
-[ ] P2 — **Fix ManagementObject disposal leak**
170
-
Why: `SystemRestoreManager.cs` line 48: WMI `ManagementObject` instances in foreach are never disposed. COM object leak.
171
-
Evidence: Code review — foreach loop over `ManagementObjectSearcher.Get()` without disposal.
172
-
Touches: `Core/Safety/SystemRestoreManager.cs`
173
-
Acceptance: ManagementObject instances disposed after use. Verify no WMI handle leaks under repeated calls.
174
-
Complexity: S
175
-
176
-
-[ ] P2 — **"Always keep" protection flag per program**
177
-
Why: Users want to protect critical apps from accidental batch uninstall. Table-stakes safety UX.
178
-
Evidence: BCU issue #935 (most-requested safety feature); Revo Pro has similar "exclude" feature.
Acceptance: Right-click → "Always Keep" marks a program. Marked programs are excluded from batch uninstall and show a lock icon. Persisted in DataPaths.Config.
181
-
Complexity: S
182
-
183
-
-[ ] P2 — **winget COM API migration**
184
-
Why: `winget list --output json` is not a supported CLI option. Current fallback to table parsing is fragile. The `Microsoft.Management.Deployment` COM API is the official programmatic interface.
Acceptance: Use `winget export` for JSON package list or COM API for real-time queries. Remove `ParseWingetTable` fallback. Add test with sample JSON output.
188
-
Complexity: M
189
-
190
-
-[ ] P2 — **External leftover signature loading**
191
-
Why: Current DB is embedded-resource only — no way for users or community to contribute profiles without recompilation.
Acceptance: On startup, scan `DataPaths.Cleaners/*.signatures.json` and merge with embedded DB. User-contributed files take precedence over embedded entries for the same app name.
195
-
Complexity: S
196
-
197
-
### P3 — Polish + differentiation
198
-
199
112
-[ ] P3 — **Expert/safe mode toggle**
200
113
Why: BleachBit's expert mode hides dangerous operations from novice users. Reduces support burden and builds trust.
0 commit comments