mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-24 12:42:38 +00:00
vulnerability matching improvements, including confidence levels and data freshness indicators. These changes enhance the accuracy and transparency of vulnerability reporting in the Autopilot Monitor application.
This commit is contained in:
@@ -1 +1 @@
|
||||
801
|
||||
802
|
||||
|
||||
@@ -56,6 +56,45 @@ public class VulnerabilityCorrelationServiceTests
|
||||
"cpe:2.3:a:cisco:anyconnect:*:*:*:*:*:*:android:*"));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// IsDescriptionNonWindowsOnly
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
[Theory]
|
||||
[InlineData("A buffer overflow vulnerability in TA for Linux and TA for MacOS prior to 5.8.1", true)]
|
||||
[InlineData("Privilege escalation in Android agent version 3.0", true)]
|
||||
[InlineData("Remote code execution in Linux kernel module", true)]
|
||||
[InlineData("Vulnerability in agent for iOS devices", true)]
|
||||
public void IsDescriptionNonWindowsOnly_OnlyNonWindowsPlatforms_ReturnsTrue(string description, bool expected)
|
||||
{
|
||||
Assert.Equal(expected, VulnerabilityCorrelationService.IsDescriptionNonWindowsOnly(description));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Vulnerability in agent for Linux, macOS, and Windows")]
|
||||
[InlineData("Buffer overflow in Windows service prior to 5.8.1")]
|
||||
[InlineData("Cross-platform issue affecting Windows and Linux")]
|
||||
public void IsDescriptionNonWindowsOnly_MentionsWindows_ReturnsFalse(string description)
|
||||
{
|
||||
Assert.False(VulnerabilityCorrelationService.IsDescriptionNonWindowsOnly(description));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Buffer overflow in processing module")]
|
||||
[InlineData("Remote code execution via crafted input")]
|
||||
public void IsDescriptionNonWindowsOnly_NoPlatformMentioned_ReturnsFalse(string description)
|
||||
{
|
||||
Assert.False(VulnerabilityCorrelationService.IsDescriptionNonWindowsOnly(description));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsDescriptionNonWindowsOnly_NullOrEmpty_ReturnsFalse()
|
||||
{
|
||||
Assert.False(VulnerabilityCorrelationService.IsDescriptionNonWindowsOnly(null));
|
||||
Assert.False(VulnerabilityCorrelationService.IsDescriptionNonWindowsOnly(""));
|
||||
Assert.False(VulnerabilityCorrelationService.IsDescriptionNonWindowsOnly(" "));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// FilterByVersion
|
||||
// -----------------------------------------------------------------------
|
||||
@@ -305,6 +344,65 @@ public class VulnerabilityCorrelationServiceTests
|
||||
Assert.Equal("CVE-2021-1258", results[0]["cveId"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FilterByVersion_DescriptionNonWindowsOnly_SkipsCve()
|
||||
{
|
||||
var svc = CreateServiceForFilterTests();
|
||||
var cves = new List<CachedCve>
|
||||
{
|
||||
new CachedCve
|
||||
{
|
||||
CveId = "CVE-2024-0213",
|
||||
CvssScore = 8.2,
|
||||
CvssSeverity = "HIGH",
|
||||
Description = "A buffer overflow vulnerability in TA for Linux and TA for MacOS prior to 5.8.1 allows a local user to gain elevated permissions.",
|
||||
PublishedDate = "2024-01-09",
|
||||
AffectedVersions = new List<CachedVersionRange>
|
||||
{
|
||||
new CachedVersionRange
|
||||
{
|
||||
// Wildcard platform — CPE filter won't catch it
|
||||
Criteria = "cpe:2.3:a:trellix:agent:*:*:*:*:*:*:*:*",
|
||||
VersionStartIncluding = "5.0",
|
||||
VersionEndExcluding = "5.8.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var results = svc.FilterByVersion(cves, "cpe:2.3:a:trellix:agent", "5.8.0.161");
|
||||
Assert.Empty(results); // Description says Linux/macOS only → filtered out
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FilterByVersion_DescriptionMentionsWindows_KeepsCve()
|
||||
{
|
||||
var svc = CreateServiceForFilterTests();
|
||||
var cves = new List<CachedCve>
|
||||
{
|
||||
new CachedCve
|
||||
{
|
||||
CveId = "CVE-2024-9999",
|
||||
CvssScore = 7.0,
|
||||
CvssSeverity = "HIGH",
|
||||
Description = "Vulnerability in agent for Linux, macOS, and Windows prior to 5.8.1.",
|
||||
PublishedDate = "2024-01-09",
|
||||
AffectedVersions = new List<CachedVersionRange>
|
||||
{
|
||||
new CachedVersionRange
|
||||
{
|
||||
Criteria = "cpe:2.3:a:trellix:agent:*:*:*:*:*:*:*:*",
|
||||
VersionStartIncluding = "5.0",
|
||||
VersionEndExcluding = "5.8.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var results = svc.FilterByVersion(cves, "cpe:2.3:a:trellix:agent", "5.8.0.161");
|
||||
Assert.Single(results); // Mentions Windows → keep it
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FilterByVersion_EmptyAffectedVersions_ReturnsEmpty()
|
||||
{
|
||||
|
||||
+50
@@ -563,6 +563,51 @@ namespace AutopilotMonitor.Functions.Services.Vulnerability
|
||||
return false;
|
||||
}
|
||||
|
||||
// Keywords that indicate a non-Windows platform in CVE descriptions.
|
||||
private static readonly string[] DescriptionNonWindowsKeywords = new[]
|
||||
{
|
||||
"linux", "macos", "mac os", "mac_os", "mac_os_x", "macintosh",
|
||||
"android", "ios", "iphone", "ipad",
|
||||
"freebsd", "openbsd", "netbsd", "solaris", "aix", "hp-ux", "hpux",
|
||||
"chrome os", "chromeos", "tvos", "watchos", "ipados", "unix"
|
||||
};
|
||||
|
||||
private static readonly string[] DescriptionWindowsKeywords = new[]
|
||||
{
|
||||
"windows", "win32", "win64", "microsoft windows"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Secondary defense: check if the CVE description explicitly mentions ONLY
|
||||
/// non-Windows platforms. Returns true when the description names at least one
|
||||
/// non-Windows OS and does NOT mention Windows at all.
|
||||
/// Conservative: if no platform is mentioned, returns false (pass through).
|
||||
/// </summary>
|
||||
internal static bool IsDescriptionNonWindowsOnly(string? description)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(description)) return false;
|
||||
|
||||
bool hasNonWindows = false;
|
||||
foreach (var kw in DescriptionNonWindowsKeywords)
|
||||
{
|
||||
if (description.Contains(kw, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
hasNonWindows = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasNonWindows) return false;
|
||||
|
||||
foreach (var kw in DescriptionWindowsKeywords)
|
||||
{
|
||||
if (description.Contains(kw, StringComparison.OrdinalIgnoreCase))
|
||||
return false; // Mentions Windows too — keep it
|
||||
}
|
||||
|
||||
return true; // Only non-Windows platforms mentioned
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Filter cached CVEs by installed version. Applies version-range logic,
|
||||
/// platform filtering (skip non-Windows CVEs), and flags wildcard matches
|
||||
@@ -640,6 +685,11 @@ namespace AutopilotMonitor.Functions.Services.Vulnerability
|
||||
if (!isAffected)
|
||||
continue;
|
||||
|
||||
// Secondary defense: if the CVE description explicitly mentions only
|
||||
// non-Windows platforms (e.g. "TA for Linux and MacOS"), filter it out.
|
||||
if (IsDescriptionNonWindowsOnly(cve.Description))
|
||||
continue;
|
||||
|
||||
var entry = new Dictionary<string, object>
|
||||
{
|
||||
{ "cveId", cve.CveId },
|
||||
|
||||
+14
-5
@@ -21,6 +21,7 @@ interface CveDetail {
|
||||
kev?: boolean;
|
||||
publishedDate?: string;
|
||||
references?: string[];
|
||||
versionMatchConfidence?: string;
|
||||
}
|
||||
|
||||
interface Finding {
|
||||
@@ -141,6 +142,7 @@ export default function VulnerabilityReportSection({
|
||||
kev: (c.kev ?? c.isKev ?? c.is_kev ?? false) as boolean,
|
||||
publishedDate: (c.publishedDate || c.published_date || "") as string,
|
||||
references: (c.references || []) as string[],
|
||||
versionMatchConfidence: (c.versionMatchConfidence || c.version_match_confidence) as string | undefined,
|
||||
}));
|
||||
|
||||
const maxCvss = cves.reduce((max: number, c: CveDetail) => Math.max(max, c.cvss ?? 0), 0);
|
||||
@@ -620,11 +622,10 @@ export default function VulnerabilityReportSection({
|
||||
)}
|
||||
|
||||
{/* Data Freshness */}
|
||||
{dataFreshness && (
|
||||
<div className="mt-3 text-xs text-gray-400">
|
||||
Data Freshness: {dataFreshness}
|
||||
</div>
|
||||
)}
|
||||
<div className="mt-3 text-xs text-gray-400">
|
||||
{dataFreshness && <>Data Freshness: {dataFreshness} · </>}
|
||||
<span className="italic">Experimental — best-effort CVE matching</span>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
@@ -863,6 +864,14 @@ function FindingRow({ finding, isExpanded, onToggle }: {
|
||||
<span>KEV</span>
|
||||
</span>
|
||||
)}
|
||||
{cve.versionMatchConfidence === "low" && (
|
||||
<span
|
||||
className="px-2 py-0.5 rounded text-xs font-medium bg-amber-50 text-amber-700 cursor-help"
|
||||
title="Version match is based on a wildcard CPE entry — the installed version may not actually be affected"
|
||||
>
|
||||
Uncertain match
|
||||
</span>
|
||||
)}
|
||||
{cve.publishedDate && (
|
||||
<span className="text-xs text-gray-400">{cve.publishedDate}</span>
|
||||
)}
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user