mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-25 05:00:07 +00:00
better namings for vulnerability report
This commit is contained in:
@@ -1 +1 @@
|
||||
880
|
||||
881
|
||||
|
||||
+10
@@ -69,6 +69,7 @@ namespace AutopilotMonitor.Functions.Services.Vulnerability
|
||||
|
||||
var findings = new List<Dictionary<string, object>>();
|
||||
var unmatchedSoftware = new List<Dictionary<string, object>>();
|
||||
var matchedCleanSoftware = new List<Dictionary<string, object>>();
|
||||
int matchedCount = 0;
|
||||
int totalCves = 0;
|
||||
int criticalCves = 0;
|
||||
@@ -128,7 +129,15 @@ namespace AutopilotMonitor.Functions.Services.Vulnerability
|
||||
}
|
||||
|
||||
if (vulns.Count == 0)
|
||||
{
|
||||
matchedCleanSoftware.Add(new Dictionary<string, object>
|
||||
{
|
||||
{ "softwareName", displayName },
|
||||
{ "installedVersion", installedVersion },
|
||||
{ "cpeUri", cpeUri }
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check KEV for each CVE
|
||||
foreach (var vuln in vulns)
|
||||
@@ -253,6 +262,7 @@ namespace AutopilotMonitor.Functions.Services.Vulnerability
|
||||
},
|
||||
{ "findings", findings },
|
||||
{ "unmatched_software", unmatchedSoftware.Take(100).ToList() },
|
||||
{ "matched_clean_software", matchedCleanSoftware.Take(200).ToList() },
|
||||
{ "data_freshness", new Dictionary<string, object>
|
||||
{
|
||||
{ "cpe_cache_entries", _cpeMappings?.Count ?? 0 },
|
||||
|
||||
+32
-10
@@ -122,11 +122,12 @@ export default function VulnerabilityReportSection({
|
||||
}, [events]);
|
||||
|
||||
// --- Findings data (wrapped in try/catch to prevent page crash on malformed report data) ---
|
||||
const { findings, unmatchedSoftware, mappedNames, unmappedNames, totalSoftware, kevTotal, dataFreshness } = useMemo(() => { try {
|
||||
const { findings, unmatchedSoftware, mappedNames, unmappedNames, cleanNames, totalSoftware, kevTotal, dataFreshness } = useMemo(() => { try {
|
||||
const findingsMap = new Map<string, Finding>();
|
||||
let unmatched: string[] = [];
|
||||
const mapped = new Set<string>();
|
||||
const unmapped = new Set<string>();
|
||||
const clean = new Set<string>();
|
||||
let total = 0;
|
||||
let freshness = "";
|
||||
let kevCount = 0;
|
||||
@@ -195,6 +196,18 @@ export default function VulnerabilityReportSection({
|
||||
}
|
||||
}
|
||||
}
|
||||
// Parse matched_clean_software (CPE mapped, no CVEs found)
|
||||
const rawClean = d.matched_clean_software;
|
||||
if (rawClean && Array.isArray(rawClean)) {
|
||||
for (const entry of rawClean) {
|
||||
if (entry && typeof entry === "object") {
|
||||
const e = entry as Record<string, unknown>;
|
||||
const label = (e.softwareName || e.software || e.name || "") as string;
|
||||
if (label) clean.add(label.toLowerCase().trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
total = (d.totalSoftware ?? d.total_software ?? d.totalCount ?? total) as number;
|
||||
const rawFreshness = d.dataFreshness || d.data_freshness || d.analyzedAt || d.analyzed_at || freshness;
|
||||
if (rawFreshness && typeof rawFreshness === "object") {
|
||||
@@ -214,11 +227,12 @@ export default function VulnerabilityReportSection({
|
||||
unmatchedSoftware: uniqueUnmatched,
|
||||
mappedNames: mapped,
|
||||
unmappedNames: unmapped,
|
||||
cleanNames: clean,
|
||||
totalSoftware: total,
|
||||
kevTotal: kevCount,
|
||||
dataFreshness: freshness,
|
||||
};
|
||||
} catch (e) { console.error("[VulnerabilityReportSection] Failed to parse findings", e); return { findings: [], unmatchedSoftware: [], mappedNames: new Set<string>(), unmappedNames: new Set<string>(), totalSoftware: 0, kevTotal: 0, dataFreshness: "" }; }
|
||||
} catch (e) { console.error("[VulnerabilityReportSection] Failed to parse findings", e); return { findings: [], unmatchedSoftware: [], mappedNames: new Set<string>(), unmappedNames: new Set<string>(), cleanNames: new Set<string>(), totalSoftware: 0, kevTotal: 0, dataFreshness: "" }; }
|
||||
}, [vulnReportData]);
|
||||
|
||||
// Severity counts for header badges
|
||||
@@ -672,7 +686,8 @@ export default function VulnerabilityReportSection({
|
||||
<tbody className="divide-y divide-gray-100">
|
||||
{filteredInventory.map((item, i) => {
|
||||
const nameLower = item.name.toLowerCase().trim();
|
||||
const isMapped = mappedNames.has(nameLower);
|
||||
const hasFindings = mappedNames.has(nameLower);
|
||||
const isClean = cleanNames.has(nameLower);
|
||||
const isUnmapped = unmappedNames.has(nameLower);
|
||||
return (
|
||||
<tr key={`${item.name}-${item.version}-${i}`} className="hover:bg-gray-50">
|
||||
@@ -691,8 +706,10 @@ export default function VulnerabilityReportSection({
|
||||
)}
|
||||
</td>
|
||||
<td className="py-2 px-3">
|
||||
{isMapped ? (
|
||||
<span className="px-2 py-0.5 rounded text-xs font-medium bg-indigo-100 text-indigo-700 cursor-help" title="Matched to CPE entry — CVE lookup available">mapped</span>
|
||||
{hasFindings ? (
|
||||
<span className="px-2 py-0.5 rounded text-xs font-medium bg-red-100 text-red-700 cursor-help" title="CVEs found for this version — action needed">vulnerable</span>
|
||||
) : isClean ? (
|
||||
<span className="px-2 py-0.5 rounded text-xs font-medium bg-green-100 text-green-700 cursor-help" title="Checked against NVD — no known vulnerabilities for this version">clean</span>
|
||||
) : isUnmapped ? (
|
||||
<span className="px-2 py-0.5 rounded text-xs font-medium bg-gray-100 text-gray-500 cursor-help" title="No CPE mapping — not checked against CVE database">unmapped</span>
|
||||
) : (
|
||||
@@ -722,7 +739,8 @@ export default function VulnerabilityReportSection({
|
||||
<span><span className="inline-block px-1.5 py-0.5 rounded bg-red-100 text-red-700 font-medium mr-1">low</span> Unidentified</span>
|
||||
<span className="basis-full h-0" />
|
||||
<span className="font-medium text-gray-500 whitespace-nowrap">CVE Mapping:</span>
|
||||
<span><span className="inline-block px-1.5 py-0.5 rounded bg-indigo-100 text-indigo-700 font-medium mr-1">mapped</span> Matched to CPE — CVE lookup available</span>
|
||||
<span><span className="inline-block px-1.5 py-0.5 rounded bg-red-100 text-red-700 font-medium mr-1">vulnerable</span> CVEs found — action needed</span>
|
||||
<span><span className="inline-block px-1.5 py-0.5 rounded bg-green-100 text-green-700 font-medium mr-1">clean</span> Checked — no known vulnerabilities</span>
|
||||
<span><span className="inline-block px-1.5 py-0.5 rounded bg-gray-100 text-gray-500 font-medium mr-1">unmapped</span> No CPE mapping configured</span>
|
||||
</div>
|
||||
</>
|
||||
@@ -760,7 +778,8 @@ export default function VulnerabilityReportSection({
|
||||
<tbody className="divide-y divide-gray-100">
|
||||
{deltaItems.map((item, i) => {
|
||||
const nameLower = item.name.toLowerCase().trim();
|
||||
const isMapped = mappedNames.has(nameLower);
|
||||
const hasFindings = mappedNames.has(nameLower);
|
||||
const isClean = cleanNames.has(nameLower);
|
||||
const isUnmapped = unmappedNames.has(nameLower);
|
||||
return (
|
||||
<tr key={`${item.name}-${item.version}-${i}`} className="hover:bg-gray-50">
|
||||
@@ -779,8 +798,10 @@ export default function VulnerabilityReportSection({
|
||||
)}
|
||||
</td>
|
||||
<td className="py-2 px-3">
|
||||
{isMapped ? (
|
||||
<span className="px-2 py-0.5 rounded text-xs font-medium bg-indigo-100 text-indigo-700 cursor-help" title="Matched to CPE entry — CVE lookup available">mapped</span>
|
||||
{hasFindings ? (
|
||||
<span className="px-2 py-0.5 rounded text-xs font-medium bg-red-100 text-red-700 cursor-help" title="CVEs found for this version — action needed">vulnerable</span>
|
||||
) : isClean ? (
|
||||
<span className="px-2 py-0.5 rounded text-xs font-medium bg-green-100 text-green-700 cursor-help" title="Checked against NVD — no known vulnerabilities for this version">clean</span>
|
||||
) : isUnmapped ? (
|
||||
<span className="px-2 py-0.5 rounded text-xs font-medium bg-gray-100 text-gray-500 cursor-help" title="No CPE mapping — not checked against CVE database">unmapped</span>
|
||||
) : (
|
||||
@@ -800,7 +821,8 @@ export default function VulnerabilityReportSection({
|
||||
<span><span className="inline-block px-1.5 py-0.5 rounded bg-red-100 text-red-700 font-medium mr-1">low</span> Unidentified</span>
|
||||
<span className="basis-full h-0" />
|
||||
<span className="font-medium text-gray-500 whitespace-nowrap">CVE Mapping:</span>
|
||||
<span><span className="inline-block px-1.5 py-0.5 rounded bg-indigo-100 text-indigo-700 font-medium mr-1">mapped</span> Matched to CPE — CVE lookup available</span>
|
||||
<span><span className="inline-block px-1.5 py-0.5 rounded bg-red-100 text-red-700 font-medium mr-1">vulnerable</span> CVEs found — action needed</span>
|
||||
<span><span className="inline-block px-1.5 py-0.5 rounded bg-green-100 text-green-700 font-medium mr-1">clean</span> Checked — no known vulnerabilities</span>
|
||||
<span><span className="inline-block px-1.5 py-0.5 rounded bg-gray-100 text-gray-500 font-medium mr-1">unmapped</span> No CPE mapping configured</span>
|
||||
</div>
|
||||
</>
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user