The Security overview and exploit-intel surfaces picked the latest scan per
image without restricting to scans that ran the vulnerability scanner, and
counted known-exploited (KEV) findings only among Critical/High. Two effects:
- A newer secret-only node scan became the latest scan for an image and
clobbered its Critical/High/fixable/KEV posture to zero, which could read a
false Secure state.
- A Medium or Low severity KEV that the pre-deploy gate blocks on produced zero
overview and exploit-intel rows, so the page disagreed with the gate.
Posture queries now select the latest vulnerability-bearing scan per image, the
image summary sources its vulnerability counts from that scan via a LEFT JOIN
while still counting secret and misconfiguration findings from the latest scan
overall, and knownExploited is counted from a dedicated any-severity KEV query
that mirrors the gate.
Scan-policy deploy gates can now block on a known-exploited CVE (CISA KEV)
and on a fixable Critical/High finding, in addition to an optional severity
threshold. New policies default risk-first (KEV and fixable on, severity off);
existing policies keep their severity-only behavior. CVSS stays captured for
context but is never the sole basis for a block, and a finding whose
exploitability cannot be confirmed is treated as risky rather than safe
(incomplete scan detail fails closed on KEV/fixable inputs).
The decision logic is shared between the pre-deploy gate and the informational
post-scan banner via a pure helper, so the two never disagree. Block messages
and the block dialog now name the conditions an image matched. Backend and
frontend gates move together, the new inputs replicate across the fleet, and a
blocking policy with no active input is rejected on both sides.
* feat: chart-led Security overview with sortable Images and History tables
Refine the Security page around the existing design system and add the
data the dashboard needs.
- Overview leads with four charts (30-day risk trend, severity donut, top
exposed images, findings by type); the signal-rail counts become a
secondary summary, and the scanner and deploy-enforcement posture follow.
- Images becomes a recessed table with search, a severity filter, sortable
columns, a last-scan column, and inline scan actions; the findings cell is
clickable into the scan sheet, and the per-row cursor tooltip is dropped
where the columns already carry that information.
- Policies puts deploy-enforcement first, collapses the policy packs into an
accordion, and uses the standard primary button for Add policy.
- Suppressions and acknowledgements move their titles and Add buttons outside
the cards, matching the Fleet tab layout.
- History switches from the detail sheet to an inline table (search, sortable
columns, two-scan compare, pagination); the now-unreachable scan-history
overlay is removed.
- Add GET /api/security/overview/trend, a node-scoped daily critical/high
rollup backing the risk-trend chart.
- Extract the shared image-scan hook and the severity classifier, and harden
the overview data fetch so a malformed non-critical response can never read
as a clean security state.
* fix: treat malformed Security responses as errors, not empty or clean states
Address an independent review of the data-fetch paths so a 200 with an
unexpected shape can never read as a benign "no findings" view.
- SecurityView: validate that the image-summaries body is a scan-summary map; an
unexpected shape now sets the error state instead of an empty map. Isolate the
trend fetch in its own self-catching promise so a transport failure on the
non-critical chart can no longer poison the overview or summaries error state.
- useImageScan: only a "completed" poll counts as success (a malformed or unknown
status now throws), and a failed post-scan summaries refresh is logged instead
of silently dropped.
- HistoryTab: a 200 whose body lacks an items array is treated as an error, not
an empty "no completed scans" list.
* feat: add dedicated Security page and policy-pack foundation
Bring vulnerability scanning, scan history, suppressions, Compose risks,
secrets, policy packs, and scanner setup into one node-scoped Security
command center instead of scattering them across Resources and Settings.
- New top-level Security view with Overview, Images, Compose risks,
Secrets, Policies, Suppressions, History, and Scanner setup tabs
(status masthead + signal rail; controlled tabs with deep-link support).
- Backend: GET /security/overview rollup and GET /security/policy-packs
static catalog (auth-only, Community). DatabaseService gains an uncapped
scan-status count and a node-eligible block-policy count, and
getImageScanSummaries now projects secret and misconfig counts.
- Reuse existing surfaces: the scan-history sheet, the control-governed
suppression and acknowledgement panels, and the scan-detail sheet (now
with an initial-tab prop so it opens on the matching finding type).
- Extract a shared SeverityBadge (from Resources) and a TrivyManager
(from Settings) so both surfaces render identical controls.
- Resources "Scan history" now links into the Security page History tab.
- Docs for the new Security surface and tests for the new endpoints,
helpers, nav wiring, and tabs.
* refactor: consolidate scanner and policy management onto the Security page
Remove the Settings "Vulnerability Scanning" section now that the Security
page covers the same ground, with every option preserved:
- Scanner install / update / uninstall / auto-update live on the Scanner setup
tab (TrivyManager).
- Scan policies, the honor-suppressions toggle, and the replica
managed-by-control / demote controls move into a new ScanPolicyManager on the
Policies tab (paid; Community sees only the policy-pack catalog).
- CVE suppressions and acknowledgements remain on the Suppressions tab.
Wiring removed: the registry section and the now-empty Security settings group,
the SectionId, the SettingsSectionContent case and the isPaid prop it was the
sole consumer of, and SecuritySection itself. The dashboard configuration-status
"Vulnerability scanning" row now navigates to the Security page Policies tab.
Docs that pointed at "Settings -> Security -> Vulnerability Scanning" are swept
to the relevant Security page tabs.
* fix: harden Security page scanner refresh, policy-load errors, and secret-only badges
Address independent-review findings on the Security page:
- Scanner setup now refreshes Trivy state when the active node changes, so the
displayed scanner status matches the node TrivyManager's actions target (both
follow x-node-id). Previously, switching nodes on the tab left stale state.
- ScanPolicyManager surfaces an explicit error state on a failed policy fetch
instead of falling through to a false "No scan policies configured".
- The shared SeverityBadge and the Images findings column no longer label a scan
"clean" when it has secrets or misconfigurations but no CVE severity
(highest_severity is derived from vulnerabilities only); they show a "Findings"
state and the secret/misconfig counts instead.
- The Overview enforcement note points to the Policies tab, not the removed
Settings section.
- The History tab auto-opens the scan-history sheet only on a deep-link (mount
with the History tab active), not on every manual tab selection.
Adds tests for the badge secret/misconfig state and the policy-load error state.