From 5779363d28f8233c64ceb3f1c0c97eba4c7228a8 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 2 Sep 2026 08:50:21 +0000 Subject: [PATCH] fix(machine-health): refresh an empty CISA KEV cache file Whitespace-only cache content left needsRefresh false, so a truncated file never self-healed. Closes #3436 Co-authored-by: ksextonmelodic --- plugins/machine-health/.claude-plugin/plugin.json | 2 +- plugins/machine-health/CHANGELOG.md | 8 ++++++++ .../audit/scripts/windows/lib/Get-CisaKevCache.ps1 | 5 +++++ .../tests/windows/lib/Get-CisaKevCache.Tests.ps1 | 11 +++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/plugins/machine-health/.claude-plugin/plugin.json b/plugins/machine-health/.claude-plugin/plugin.json index b27760ebcc..3fd09f9377 100644 --- a/plugins/machine-health/.claude-plugin/plugin.json +++ b/plugins/machine-health/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "machine-health", - "version": "0.12.1", + "version": "0.12.2", "description": "Workstation health audit: OS-specific checks (disk, OS updates, security posture, CISA KEV correlation) run from a versioned catalog with trend-aware severity, approval-gated remediations, and dated markdown reports. Windows fully implemented; macOS/Linux scaffolded (report UNKNOWN and stop). Machine state persists in the plugin data directory; the report directory and check catalog are configurable.", "author": { "name": "Melodic Software", diff --git a/plugins/machine-health/CHANGELOG.md b/plugins/machine-health/CHANGELOG.md index 0fb578f789..22e4224d04 100644 --- a/plugins/machine-health/CHANGELOG.md +++ b/plugins/machine-health/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to the `machine-health` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.12.2] + +### Fixed + +- **`Get-CisaKevCache` refreshes an empty or whitespace cache file.** That path left + `needsRefresh` false and `$cached` null, so a truncated cache never self-healed. Empty + content now takes the same refresh path as a missing file. + ## [0.12.1] ### Changed diff --git a/plugins/machine-health/skills/audit/scripts/windows/lib/Get-CisaKevCache.ps1 b/plugins/machine-health/skills/audit/scripts/windows/lib/Get-CisaKevCache.ps1 index a9669271d7..c8d3a385cd 100644 --- a/plugins/machine-health/skills/audit/scripts/windows/lib/Get-CisaKevCache.ps1 +++ b/plugins/machine-health/skills/audit/scripts/windows/lib/Get-CisaKevCache.ps1 @@ -53,6 +53,11 @@ function Get-CisaKevCache { $raw = Get-Content -LiteralPath $CachePath -Raw -ErrorAction Stop if (-not [string]::IsNullOrWhiteSpace($raw)) { $cached = $raw | ConvertFrom-Json -ErrorAction Stop + } else { + # Empty or whitespace is the same class as a missing file: the + # cache cannot be reused and must refresh (#3436). Leaving + # needsRefresh false here skipped every other malformed path. + $needsRefresh = $true } } catch { Write-Warning "Get-CisaKevCache: cache parse failed, will refresh. $($_.Exception.Message)" diff --git a/plugins/machine-health/skills/audit/tests/windows/lib/Get-CisaKevCache.Tests.ps1 b/plugins/machine-health/skills/audit/tests/windows/lib/Get-CisaKevCache.Tests.ps1 index 7192f6df69..609ec4fc80 100644 --- a/plugins/machine-health/skills/audit/tests/windows/lib/Get-CisaKevCache.Tests.ps1 +++ b/plugins/machine-health/skills/audit/tests/windows/lib/Get-CisaKevCache.Tests.ps1 @@ -52,6 +52,17 @@ Describe 'Get-CisaKevCache' -Tag 'lib' { Should -Invoke Invoke-WebRequest -Times 1 } + It 'fetches when the cache file is empty or whitespace' { + Set-Content -LiteralPath $script:cachePath -Value " `r`n`t " -Encoding utf8 + + Set-KevFetchMock -CveId 'CVE-2024-EMPTY' + + $result = Get-CisaKevCache -CachePath $script:cachePath -LogPath $script:logPath + $result.vulnerabilities.Count | Should -Be 1 + $result.vulnerabilities[0].cveID | Should -Be 'CVE-2024-EMPTY' + Should -Invoke Invoke-WebRequest -Times 1 + } + It 'fetches when the cache is the checked-in seed stub (empty vulnerabilities)' { $stub = '{"_comment":"placeholder","vulnerabilities":[]}' Set-Content -LiteralPath $script:cachePath -Value $stub -Encoding utf8