From ae0e4b86dd75fca1c80f1f305f747f5b713955a0 Mon Sep 17 00:00:00 2001 From: Binh Date: Fri, 11 Sep 2026 16:03:47 +0200 Subject: [PATCH] fix: Adjust NvdCveClient to correctly handle baseSeverity from CVSS metrics --- .gitignore | 1 + docs/IMPLEMENTATION_PLAN.md | 2 + server/cve/nvd-cve-client.ts | 4 +- .../DefenderVulnerabilityPanel.tsx | 64 +++++++----- .../defender-for-iot-source-extractor.ts | 15 +-- src/styles/defender-for-iot.css | 8 +- tests/features/defender-dashboard.test.ts | 4 +- .../defender-inline-drilldown.test.tsx | 99 +++++++++++++++++++ tests/importers/defender-for-iot.test.ts | 8 +- tests/server/nvd-cve-client.test.ts | 9 +- 10 files changed, 172 insertions(+), 42 deletions(-) create mode 100644 tests/features/defender-inline-drilldown.test.tsx diff --git a/.gitignore b/.gitignore index f7a6652..7eef6e7 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ vite.config.js vite.config.d.ts *.png artifacts/objects/ +Mock-Defender/ .env.postgres .assessor-data/ diff --git a/docs/IMPLEMENTATION_PLAN.md b/docs/IMPLEMENTATION_PLAN.md index 79126c3..e4b9ef5 100644 --- a/docs/IMPLEMENTATION_PLAN.md +++ b/docs/IMPLEMENTATION_PLAN.md @@ -2,6 +2,8 @@ Status: lebendes Projektdokument +Defender-for-IoT-Drilldowns 2026-09-11 (Phase 7): CVE-, Device- und Site-Details erscheinen inline unter der ausgewaehlten Zeile mit stabilen, zugaenglichen Auf-/Zuklappzielen und gemeinsamer gelber Auswahlmarkierung. CVE-Evidenz zeigt betroffene Geraete flach; redundante Beschreibungs-, Observation- und Sensorangaben bleiben in den jeweils passenden Detailkontexten statt in der Uebersicht. Die Detailflaeche verwendet die gemeinsame Tile-Oberflaeche. Der NVD-Adapter uebernimmt `baseSeverity` aus den CVSS-Metriken. Reine Darstellungs-/Adapterkorrektur ohne Persistenz- oder Reimportaenderung. + Defender-for-IoT-Client-Info-Stil 2026-09-11 (Phase 7): Microsoft Defender for IoT bleibt eine eigenstaendige Client-Info-Registerkarte mit CVE-, Device- und Site-Ansichten. Sie verwendet denselben themenabhaengigen Client-Info-Canvas, dieselbe Kopfzeile, denselben Panel-Inset sowie die flache Kachel-, Flaechen-, Typografie-, Auswahl- und Responsive-Grammatik wie Overview. Scannerprojektion, Finding-Semantik, Scoreberechnung, Import- und Persistenzvertraege bleiben unveraendert; kein Reimport erforderlich. Maester-Unicode-Null-Import 2026-09-20 (Phase 13A/13C, Nutzerfehlerbericht, umgesetzt und verifiziert): Ein nativer Maester-Fehlertext enthielt `U+0000`. Vorschau und Mapping waren erfolgreich, der atomare PostgreSQL-Abschluss scheiterte jedoch, weil `jsonb` dieses Zeichen nicht repraesentieren kann; die bisherige Auto-Import-Fehlerbehandlung ersetzte danach die erfolgreiche Vorschau irrefuehrend durch `0 of 0 files selected`. Die gemeinsame kanonische Importgrenze stellt jedes solche Zeichen nun explizit als lesbares `\\u0000` dar, behaelt den gesamten umgebenden Quellwert, Hash und Locator und erzeugt die Diagnose `unicode-null-escaped`. Andere Steuerzeichen, Parsing, Profilwahl, Normalisierung und Bewertung bleiben unveraendert. Nach einem Abschlussfehler bleibt die vorbereitete Dateizeile samt Wiederholungsmoeglichkeit sichtbar. Ein synthetischer Maester-XLSX-Test und der vollstaendige HTTP-Pfad Vorschau -> bestaetigte Zuordnung -> Import in vorhandenen Timeslot sichern genau die Regression; 26 fokussierte Tests, Client-/Server-Produktionsbuild, Local-only- und Designpruefung bestehen. Der optionale PostgreSQL-Testlauf wurde gemaess kanonischer-Datastore-Regel nicht gegen die bestehende Kundendatenbank ausgefuehrt. Keine Migration, Schema- oder Bestandsdatenaenderung; Phase 13A bleibt abgeschlossen, Phase 13C in Arbeit. diff --git a/server/cve/nvd-cve-client.ts b/server/cve/nvd-cve-client.ts index afce7b3..b3d779e 100644 --- a/server/cve/nvd-cve-client.ts +++ b/server/cve/nvd-cve-client.ts @@ -63,12 +63,14 @@ function metrics(value: unknown): CveMetric[] { const baseScore = number(data?.baseScore); const vector = string(data?.vectorString); if (!item || !data || baseScore === undefined || !vector) return []; + // CVSS v3.x/v4.0 carry baseSeverity inside cvssData; CVSS v2 carries it on the metric entry itself. + const baseSeverity = string(data.baseSeverity) || string(item.baseSeverity); return [{ version, source: string(item.source) || 'unknown', ...(string(item.type) ? { type: string(item.type) } : {}), baseScore, - ...(string(data.baseSeverity) ? { baseSeverity: string(data.baseSeverity) } : {}), + ...(baseSeverity ? { baseSeverity } : {}), vector, ...(number(item.exploitabilityScore) === undefined ? {} : { exploitabilityScore: number(item.exploitabilityScore) }), ...(number(item.impactScore) === undefined ? {} : { impactScore: number(item.impactScore) }) diff --git a/src/features/defender-for-iot/DefenderVulnerabilityPanel.tsx b/src/features/defender-for-iot/DefenderVulnerabilityPanel.tsx index 8d7e3db..a721bca 100644 --- a/src/features/defender-for-iot/DefenderVulnerabilityPanel.tsx +++ b/src/features/defender-for-iot/DefenderVulnerabilityPanel.tsx @@ -1,4 +1,5 @@ -import { useMemo, useState, type ReactNode } from 'react'; +import { Fragment, useMemo, useState, type ReactNode } from 'react'; +import { TriangleIcon } from '../../components/TriangleIcon'; import type { DefenderDevice, DefenderSeverity, DefenderSeverityMeasure } from '../../domain/defender-for-iot'; import type { ImportedDataset } from '../../domain/dataset'; import { WorkTimeslotControl } from '../search-filter/WorkTimeslotControl'; @@ -28,17 +29,17 @@ function SeverityMark({ severity }: { severity: DefenderSeverity | 'unknown' }) return