Skip to content

Surface heuristic scanner failures instead of swallowing at Debug (#140) - #141

Merged
sanderdewit merged 1 commit into
mainfrom
feat/surface-scanner-failures-140
Jul 8, 2026
Merged

Surface heuristic scanner failures instead of swallowing at Debug (#140)#141
sanderdewit merged 1 commit into
mainfrom
feat/surface-scanner-failures-140

Conversation

@sanderdewit

Copy link
Copy Markdown
Owner

Closes #140.

Problem

Get-MsixHeuristicFinding runs each read-only scanner in its own try { … } catch { Write-MsixLog -Level Debug … }. Swallowing at Debug means a scanner that fails for an environmental reason (missing DLL, absent tool, denied path in a headless image) silently drops an entire finding category — and the report looks identical to a genuinely clean package. 0.73.3 fixed the specific offreg.dll case; this generalizes the pattern.

Changes

  • _MsixAddScannerError — on a scanner throw, logs at Warning and appends a low-severity ScannerError finding naming the scanner + underlying error. [AllowEmptyCollection()] so it binds even when the first scanner fails before any finding is added (caught by a test — would have been a real bind failure).
  • _MsixAddOffregScannerError — the 6 registry-derived scanners (ShellExt/ShellVerb, services, preview/property/thumbnail handlers, uninstall keys, run keys, COM servers) defer to the single OfflineRegistryUnavailable umbrella finding when offreg.dll is absent, so they don't emit 6 redundant ScannerError findings for one root cause. A genuine failure while offreg is present still surfaces.
  • Every catch in Get-MsixHeuristicFinding now routes through the right helper.
  • The Run-key scanner (offreg-dependent) was previously unwrapped — on a host without offreg.dll it threw DllNotFoundException that aborted the whole analysis. Now wrapped + gated. The Uninstaller and Alias loops were wrapped too for consistency.
  • Minor (issue's own note): the availability-probe catch in _MsixTestOffregAvailable now Debug-logs.
  • Version bump 0.73.4 + notes/CHANGELOG.

"Expected empty vs failed"

The issue asks to distinguish scanner ran, found nothing from scanner threw. This is structurally satisfied: a catch only fires on a throw; an empty result simply adds no finding and never enters the catch. No extra detection needed.

Validation

  • PSSA clean on both files.
  • New MSIX.Tests/MSIX.ScannerError.Tests.ps1: 4/4 pass (unit-tests both helpers incl. the offreg-suppression path).
  • Heuristics / Recommendations / Scanner / OfflineRegistry / SelectiveRegistry / Static suites: 44 passed, 0 failed.

Newly-surfaced latent bug (follow-up, not fixed here)

Running the suite now logs Heuristic scanner 'ManifestFix' failed … null-valued expression against a fixture — a pre-existing NRE in the ManifestFix block that was silently swallowed before and is now visible (exactly what #140 is meant to expose). Tests pass (nothing asserts on it). Worth a separate issue to fix the NRE so those manifest-fix findings aren't dropped for that manifest shape.

No release cut.

🤖 Generated with Claude Code

Get-MsixHeuristicFinding runs each read-only scanner in its own try/catch so
one broken scanner can't abort the analysis, but the catch swallowed the
failure at Debug level - a scanner failing for an environmental reason
(missing DLL, absent tool, denied path in a headless image) silently dropped
an entire finding category, and the report looked identical to a clean package.

- _MsixAddScannerError: logs Warning + appends a low-severity ScannerError
  finding naming the scanner + error. AllowEmptyCollection so it binds even when
  the first scanner fails before any finding is added.
- _MsixAddOffregScannerError: registry-derived scanners defer to the single
  OfflineRegistryUnavailable umbrella finding when offreg.dll is absent (no
  redundant per-scanner ScannerError); genuine failures while offreg is present
  still surface.
- Route every Debug-swallow catch in Get-MsixHeuristicFinding through these.
- Wrap + gate the Run-key scanner (offreg-dependent, previously UNWRAPPED - it
  could abort the whole analysis on a host without offreg.dll). Wrap the
  Uninstaller and Alias loops too for consistency.
- _MsixTestOffregAvailable probe catch now Debug-logs (issue minor point).
- Regression tests in MSIX.ScannerError.Tests.ps1; bump 0.73.4 + notes/CHANGELOG.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sanderdewit
sanderdewit merged commit 3d75ee4 into main Jul 8, 2026
6 checks passed
@sanderdewit
sanderdewit deleted the feat/surface-scanner-failures-140 branch July 8, 2026 19:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Offline-registry scanners swallow failures at Debug level — surface a diagnostic when a scanner errors

1 participant