Acknowledge / suppress / postpone vulnerabilities in triage #22
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Motstandskraft/spam#22
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Goal
Let users acknowledge / suppress vulnerabilities surfaced in the triage buckets, with two modes:
Today there is no per-user acknowledge/postpone concept. The only durable override is VEX (
component_vex, keyed by(PURL, VulnID), statusesaffected / not_affected / fixed / under_investigation) set viaPOST /api/dependencies/vex(api/internal/uiapi/vulnerabilities.go:42). VEX filters findings out of counts and the triage detail panel (api/internal/uiapi/triage_image_detail.go:80). The LLM advisory verdict (keep/suppress) is shadow-mode / display-only (api/internal/assetrisk/metrics.go:93).Why VEX alone is not enough
VEX is a global statement about a component+CVE pair ("this PURL is not_affected by this CVE"). Acknowledge/postpone is an operational, scoped, time-boxed decision ("I've seen this on this image, deal with it later"). These are different axes — we need a new suppression record that can be scoped and time-boxed, and can optionally emit a VEX record when the justification is a true VEX statement.
Proposed model
New table
finding_suppression(GORM in a newinternal/triageor extendinternal/vulnerabilities):iduuid PKkindpostpone|suppressscope_typeglobal|asset|vuln|asset_vulnasset_type/asset_ref_idIMAGE_DIGEST/REPO_COMMIT(matchesSBOMBinding)vuln_idpurlcommentsuppress; optional forpostponevex_justificationcomponent_vexsnooze_untilsuppresscreated_by_user_id,created_atrevoked_by_user_id,revoked_atSuppressions are applied as a filter in the triage queries (
triage_dashboard.go,triage_image_detail.go,vulnmetrics.LoadListPage) and must be re-evaluated againstsnooze_untilat read time so postponed items resurface.Edge cases to define (the hard part)
image_digests.id— does a digest-scoped suppression carry forward? Proposal: allowasset_vuln(this digest) and a repo/image-name-scoped option that survives re-tags.installed_versionpredicate so a different vulnerable version re-surfaces.watchCVE is postponed 90d, then lands on CISA KEV / becomes internet-exposed / EPSS spikes. Should a postpone be auto-broken when the finding would now befix_now? Proposal: yes — postpone suppresses display, but a configurable severity-escalation rule re-surfaces it early and notes "re-opened: now actively exploited".code_not_reachable, do we also writecomponent_vex? That makes it global across all assets — may be wider than intended. Proposal: suppression stays scoped; only emit VEX when the user explicitly picks "apply as VEX (all assets)".vuln_dashboard_snapshots), or just out of the actionable triage view? Proposal: keep them in raw counts, exclude from actionable tiers, expose a "suppressed" filter/badge.acl.Provider). A user can only suppress findings on assets they can see. Revoking another user's suppression — admin only? team-wide?internal/audit(append-only), since this is a risk-acceptance decision.vulnmetrics/ triage caches viaTriggerRefresh().API sketch
POST /api/triage/suppress—{scope, asset_type?, asset_ref_id?, vuln_id?, purl?, kind, snooze_until?, comment, vex_justification?}DELETE /api/triage/suppress/{id}— revokeGET /api/triage/suppressions?asset_type=&asset_ref_id=— list (for "show suppressed" toggle)suppressedsection + per-findingsuppressionmetadata.Tasks
finding_suppressionDepends on / relates to: notifications epic (postpone-expiry + escalation notifications).