feat(security): prioritization-led Overview charts (posture + exploit intel) (#1427)

* feat(security): rework Overview charts around posture and exploit intel

Replace the three severity-variation charts (severity donut, top exposed images,
findings by type) with prioritization views, keeping the risk trend for context:

- Action posture: bars of fixable / known-exploited / needs-review / accepted /
  not-affected with a known-exploited headline, derived from the existing
  overview facts (no new fetch).
- Top exploit-risk findings: ranked actionable Critical/High by KEV, then EPSS,
  then CVSS, each row opening its scan.
- Severity x exploitability: a CVSS-by-EPSS quadrant that separates
  scary-but-not-exploitable from act-first.

The two intel panels are fed by a new bounded GET /security/overview/exploit-intel
(latest-scan Critical/High, suppression-filtered, KEV/EPSS joined at read time)
and degrade to clear empty states until exploit intel is fetched and images are
rescanned.

* fix(security): drop the redundant SECURITY kicker from the desktop masthead

The desktop nav strip already names the page, so the masthead's "SECURITY" label
above the posture word was redundant. Make PageMasthead's kicker optional (pages
that pass one render unchanged) and omit it on the Security masthead. The mobile
masthead keeps its kicker, since on the phone layout it is the page identity and
there is no nav strip.

* docs(security): describe the prioritization-led Overview charts

Update the Security overview docs for the reworked chart set (risk trend, action
posture, top exploit-risk, and the severity-by-exploitability quadrant) and note
the exploit-risk charts populate once exploit intelligence is enabled.

* fix(security): move the scanner-detections note into a masthead info icon

Replace the standing "scanner detections show vulnerable components..." caption
below the masthead (desktop and mobile) with an info affordance next to the
scanned-images count in the masthead subtitle. Declutters the overview while
keeping the disclaimer one hover away.

* fix(security): apply "assume it's automatable" to exploit-risk ranking

Absence of exploitability evidence must not be treated as low risk. Rank the top
exploit-risk list by tier (known-exploited > known-high EPSS > unknown EPSS >
known-low EPSS) so an unrated finding outranks one with evidence of low
likelihood; label unrated findings "EPSS n/a"; and reword the quadrant footnote
so excluded findings read as unrated rather than lower risk.
This commit is contained in:
Anso
2026-06-23 21:55:11 -04:00
committed by GitHub
parent f794702171
commit b1630788ba
10 changed files with 527 additions and 212 deletions
+8 -3
View File
@@ -27,9 +27,14 @@ posture itself: a vulnerable component being present is not the same as a reacha
The masthead carries a standing note to that effect, and posture weighs fix availability, exploit
intelligence, and triage decisions rather than raw severity alone.
Below it, a signal rail summarizes the supporting numbers: scanned images, fixable findings, secrets,
Compose misconfigurations, stale scans, and failed scans. A status strip shows scanner health
(installed source and version, auto-update) and the active node's deploy enforcement posture.
Below it, the charts lead with prioritization rather than raw severity: a **risk trend** for context,
an **action posture** breakdown (fixable, known-exploited, needs-review, accepted, not-affected), a
**top exploit-risk** list ranking actionable findings by known-exploited status then EPSS, and a
**severity-by-exploitability** quadrant that separates high-severity-but-unlikely findings from the
ones to act on first. The exploit-risk charts populate once exploit intelligence is enabled and images
are scanned. A signal rail summarizes the supporting numbers (scanned images, fixable findings,
secrets, Compose misconfigurations, stale scans, failed scans), and a status strip shows scanner health
and the active node's deploy enforcement posture.
If a node does not report an overview (for example an older remote node), the page falls back to a
clear "overview unavailable" state and the other tabs keep working.