Merge branch 'main' of https://git.stella-ops.org/stella-ops.org/git.stella-ops.org
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

This commit is contained in:
2025-11-29 01:36:32 +02:00
231 changed files with 47468 additions and 68 deletions

View File

@@ -0,0 +1,523 @@
# Vulnerability Triage UX & VEX-First Decisioning
**Version:** 1.0
**Date:** 2025-11-28
**Status:** Canonical
This advisory defines the **end-to-end UX and data contracts** for vulnerability triage, VEX decisioning, evidence/explainability views, and audit export in Stella Ops. It synthesizes patterns from Snyk, GitLab SCA, Harbor/Trivy, and Anchore Enterprise into a converged UX layer.
---
## 1. Scope
This spec covers:
1. **Vulnerability triage** (first touch)
2. **Suppression / "Not Affected"** (VEX-aligned)
3. **Evidence & explainability views**
4. **Audit export** (immutable bundles)
5. **Attestations** as the backbone of evidence and gating
Stella Ops is the **converged UX layer** over scanner backends (Snyk, Trivy, GitLab, Anchore, or others).
---
## 2. Industry Pattern Analysis
### 2.1 Triage (First Touch)
| Tool | Pattern | Stella Ops Mirror |
|------|---------|-------------------|
| **Snyk** | PR checks show before/after diffs; Fix PRs directly from Issues list | Evidence-first cards with "Fix PR" CTA |
| **GitLab SCA** | Vulnerability Report with `Needs triage` default state | Status workflow starting at `DETECTED` |
| **Harbor/Trivy** | Project -> Artifacts -> Vulnerabilities panel with Rescan CTA | Artifact-centric navigation with scan badges |
| **Anchore** | Images -> Vulnerabilities aligned to Policies (pass/fail) | Policy gate indicators on all finding views |
**UI pattern to reuse:** An **evidence-first card** per finding (CVE, package, version, path) with primary actions (Fix PR, Dismiss/Not Affected, View Evidence).
### 2.2 Suppression / "Not Affected" (VEX-Aligned)
| Tool | Pattern | Stella Ops Mirror |
|------|---------|-------------------|
| **Snyk** | "Ignore" with reason + expiry; org-restricted; PR checks skip ignored | VEX `statusJustification` with validity window |
| **GitLab** | `Dismissed` status with required comment; activity log | VEX decisions with actor/timestamp/audit trail |
| **Anchore** | Allowlists + Policy Gates + VEX annotations | Allowlist integration + VEX buttons |
| **Harbor/Trivy** | No native VEX; store as in-toto attestation | Attestation-backed VEX decisions |
**UI pattern to reuse:** An **Actionable VEX** button (`Not Affected`, `Affected - mitigated`, `Fixed`) that opens a compact form: justification, evidence links, scope, expiry -> generates/updates a signed VEX note.
### 2.3 Evidence View (Explainability)
| Tool | Pattern | Stella Ops Mirror |
|------|---------|-------------------|
| **Snyk** | PR context + Fix PR evidence + ignore policy display | Explainability panel with PR/commit links |
| **GitLab** | Vulnerability Report hub with lifecycle activity | Decision history timeline |
| **Anchore** | Policy Gates breakdown showing which trigger caused fail/pass | Gate evaluation with trigger explanations |
| **Harbor/Trivy** | Scanner DB date, version, attestation links | Scanner metadata + attestation digest |
**UI pattern to reuse:** An **Explainability panel** on the right: "Why this is flagged / Why it passed" with timestamps, rule IDs, feed freshness, and the **Attestation digest**.
### 2.4 Audit Export (Immutable)
| Tool | Export Contents |
|------|-----------------|
| **Snyk** | PR check results + Ignore ledger + Fix PRs |
| **GitLab** | Vulnerability Report with status history |
| **Anchore** | Policy Bundle eval JSON as primary audit unit |
| **Harbor/Trivy** | Trivy report + signed attestation |
**UI pattern to reuse:** **"Create immutable audit bundle"** CTA that writes a ZIP/OCI artifact containing reports, VEX, policy evals, and attestations, plus a top-level manifest with hashes.
---
## 3. Core Data Model
### 3.1 Artifact
```text
Artifact
- id (string, stable)
- type (IMAGE | REPO | SBOM | FUNCTION | HOST)
- displayName
- coordinates (registry/repo URL, tag, branch, env, etc.)
- digests[] (e.g. sha256 for OCI images, commit SHA for repos)
- latestScanAttestations[] (AttestationRef)
- riskSummary (openCount, totalCount, maxSeverity, lastScanAt)
```
### 3.2 VulnerabilityFinding
```text
VulnerabilityFinding
- id (string, internal stable ID)
- sourceFindingId (string, from Snyk/Trivy/etc.)
- scanner (name, version)
- artifactId
- vulnerabilityId (CVE, GHSA, etc.)
- title
- severity (CRITICAL | HIGH | MEDIUM | LOW | INFO)
- package (name, version, ecosystem)
- location (filePath, containerLayer, function, callPath[])
- introducedBy (commitId?, imageDigest?, buildId?)
- firstSeenAt
- lastSeenAt
- status (DETECTED | RESOLVED | NO_LONGER_DETECTED)
- currentVexDecisionId? (if a VEX decision is attached)
- evidenceAttestationRefs[] (AttestationRef[])
```
### 3.3 VEXDecision
Represents a **VEX-style statement** attached to a finding + subject.
```text
VEXDecision
- id
- vulnerabilityId (CVE, etc.)
- subject (ArtifactRef / SBOM node ref)
- status (NOT_AFFECTED | AFFECTED_MITIGATED | AFFECTED_UNMITIGATED | FIXED)
- justificationType (enum; see section 7.3)
- justificationText (free text)
- evidenceRefs[] (links to PRs, commits, tickets, docs, etc.)
- scope (envs/projects where this decision applies)
- validFor (notBefore, notAfter?)
- attestationRef? (AttestationRef)
- supersedesDecisionId?
- createdBy (id, displayName)
- createdAt
- updatedAt
```
### 3.4 Attestation / AttestationRef
```text
AttestationRef
- id
- type (VULN_SCAN | SBOM | VEX | POLICY_EVAL | OTHER)
- statementId (if DSSE/Intoto)
- subjectName
- subjectDigest (e.g. sha256)
- predicateType (URI)
- createdAt
- signer (name, keyId)
- storage (ociRef | bundlePath | url)
```
### 3.5 PolicyEvaluation
```text
PolicyEvaluation
- id
- subject (ArtifactRef)
- policyBundleVersion
- overallResult (PASS | WARN | FAIL)
- gates[] (GateResult)
- attestationRef? (AttestationRef)
- evaluatedAt
```
### 3.6 AuditBundle
Represents a **downloadable immutable bundle** (ZIP or OCI artifact).
```text
AuditBundle
- bundleId
- version
- createdAt
- createdBy
- subject (ArtifactRef)
- index (AuditBundleIndex) <- JSON index inside the bundle
```
---
## 4. Primary UX Surfaces
### 4.1 Artifacts List
**Goal:** High-level "what's risky?" view and entry point into triage.
**Columns:**
- Artifact
- Type
- Environment(s)
- Open / Total vulns
- Max severity
- **Attestations** (badge w/ count)
- Last scan (timestamp + scanner)
**Actions:**
- View vulnerabilities (primary)
- View attestations
- Create audit bundle
### 4.2 Vulnerability Workspace (per Artifact)
**Split layout:**
**Left: Vulnerability list**
- Filters: severity, status, VEX status, scanner, package, introducedBy, env
- Sort: severity, recency, package, path
- Badges for:
- `New` (first seen in last N scans)
- `VEX: Not affected`
- `Policy: blocked` / `Policy: allowed`
**Right: Evidence / Explainability panel**
Tabs:
1. **Overview**
- Title, severity, package, version, path
- Scanner + db date
- Finding history timeline
- Current VEX decision summary (if any)
2. **Reachability**
- Call path, modules, runtime usage info (when available)
3. **Policy**
- Policy evaluation: which gate caused pass/fail
- Links to gate definitions
4. **Attestations**
- All attestations that mention:
- this artifact
- this vulnerabilityId
- this scan result
**Primary actions per finding:**
- **VEX: Set status** -> opens VEX Modal (see 4.3)
- **Open Fix PR / View Fix** (if available from Snyk/GitLab)
- **Attach Evidence** (link tickets / docs)
- **Copy audit reference** (findingId + attestation digest)
### 4.3 VEX Modal - "Affect & Justification"
**Entry points:**
- From a finding row ("VEX" button)
- From a policy failure explanation
- From a bulk action on multiple findings
**Fields (backed by `VEXDecision`):**
- Status (radio buttons):
- `Not affected`
- `Affected - mitigated`
- `Affected - not mitigated`
- `Fixed`
- Justification type (select - see section 7.3)
- Justification text (multi-line)
- Scope:
- Environments (multi-select)
- Projects / services (multi-select)
- Validity:
- Start (defaults now)
- Optional expiry (recommended)
- Evidence:
- Add links (PR, ticket, doc, commit)
- Attach attestation (optional; pick from list)
- Review:
- Summary of what will be written to the VEX statement
- "Will generate signed attestation" note (if enabled)
**Actions:**
- Save (creates or updates VEXDecision, writes VEX attestation)
- Cancel
- View raw JSON (for power users)
### 4.4 Attestations View
Per artifact, tab: **Attestations**
Table of attestations:
- Type (vuln scan, SBOM, VEX, policy)
- Subject name (shortened)
- Predicate type (URI)
- Scanner / policy engine (derived from predicate)
- Signer (keyId, trusted/not-trusted badge)
- Created at
- Verified (yes/no)
Click to open:
- Header: statement id, subject, signer
- Predicate preview:
- For vuln scan: counts, scanner version, db date
- For SBOM: bomRef, component counts
- For VEX: decision status, vulnerabilityId, scope
### 4.5 Policy & Gating View
Per environment / pipeline:
- Matrix of **gates** vs **subject types**:
- e.g. `CI Build`, `Registry Admission`, `Runtime Admission`
- Each gate shows:
- Rule description (severity thresholds, allowlist usage, required attestations)
- Last evaluation stats (pass/fail counts)
- Clicking a gate shows:
- Recent evaluations (with link to artifact & policy attestation)
- Which condition failed
### 4.6 Audit Export - Bundle Creation
**From:**
- Artifact page (button: "Create immutable audit bundle")
- Pipeline run detail
- Policy evaluation detail
**Workflow:**
1. User selects:
- Subject artifact + digest
- Time window (e.g. "last 7 days of scans & decisions")
- Included content (checklist):
- Vuln reports
- SBOM
- VEX decisions
- Policy evaluations
- Raw attestations
2. Backend generates:
- ZIP or OCI artifact
- `audit-bundle-index.json` at root
3. UI shows:
- Bundle ID & hash
- Download button
- OCI reference (if pushed to registry)
---
## 5. State Model
### 5.1 Finding Status vs VEX Status
Two separate but related states:
**Finding.status:**
- `DETECTED` - currently reported by at least one scanner
- `NO_LONGER_DETECTED` - was present, not in latest scan for this subject
- `RESOLVED` - confirmed removed (e.g. package upgraded, image replaced)
**VEXDecision.status:**
- `NOT_AFFECTED`
- `AFFECTED_MITIGATED`
- `AFFECTED_UNMITIGATED`
- `FIXED`
**UI rules:**
- If `Finding.status = NO_LONGER_DETECTED` and a VEXDecision still exists:
- Show badge: "Historical VEX decision (finding no longer detected)"
- If `VEXDecision.status = NOT_AFFECTED`:
- Policy engines may treat this as **non-blocking** (configurable)
---
## 6. Interaction Patterns to Mirror
### 6.1 From Snyk
- PR checks show **before/after** and don't fail on ignored issues
- Action: "Fix PR" from a finding
- Mapping:
- Stella Ops should show "Fix PR" and "Compare before/after" where data exists
- VEX `NOT_AFFECTED` should make **future checks ignore** that finding for that subject/scope
### 6.2 From GitLab SCA
- `Dismissed` with reasons and activity log
- Mapping:
- VEX decisions must have reason + actor + timestamp
- The activity log should show a full **decision history**
### 6.3 From Anchore
- Policy gates & allowlists
- Mapping:
- Gate evaluation screen with clear "this gate failed because..." explanation
---
## 7. Enumerations & Conventions
### 7.1 VEX Status
```text
NOT_AFFECTED
AFFECTED_MITIGATED
AFFECTED_UNMITIGATED
FIXED
```
### 7.2 VEX Scope
- `envs[]`: e.g. `["prod", "staging"]`
- `projects[]`: service / app names
- Default: applies to **all** unless restricted
### 7.3 Justification Type (inspired by CSAF/VEX)
```text
CODE_NOT_PRESENT
CODE_NOT_REACHABLE
VULNERABLE_CODE_NOT_IN_EXECUTE_PATH
CONFIGURATION_NOT_AFFECTED
OS_NOT_AFFECTED
RUNTIME_MITIGATION_PRESENT
COMPENSATING_CONTROLS
ACCEPTED_BUSINESS_RISK
OTHER
```
---
## 8. Attestation Placement
### 8.1 Trivy + Cosign
Generate **vulnerability-scan attestation** and SBOM attestation; attach to image via OCI referrers. These attestations become the source of truth for evidence and audit export.
### 8.2 Harbor
Treat attestations as first-class accessories/refs to the image. Surface them next to the Vulnerabilities tab. Link them into the explainability panel.
### 8.3 Anchore
Reference attestation digests inside **Policy evaluation** output so pass/fail is traceable to signed inputs.
### 8.4 Snyk/GitLab
Surface attestation presence in PR/Security dashboards to prove findings came from a **signed** scan; link out to the OCI digest.
**UI pattern:** Small **"Signed evidence"** pill on each finding; clicking opens the attestation JSON (human-readable view) + verify command snippet.
---
## 9. Gating Controls
| Tool | Mechanism | Stella Ops Mirror |
|------|-----------|-------------------|
| **Anchore** | Policy Gates/Triggers model for hard gates | Gates per environment with trigger explainability |
| **Snyk** | PR checks + Auto Fix PRs as soft gates | PR integration with soft/hard gate toggles |
| **GitLab** | MR approvals + Security Policies; auto-resolve on no-longer-detected | Status-aware policies with auto-resolution |
| **Harbor** | External policy engines (Kyverno/OPA) verify signatures/attestations | Admission controller integration |
---
## 10. Minimal UI Wireframe
### 10.1 Artifacts List
| Image | Tag | Risk (open/total) | Attestations | Last scan |
|-------|-----|-------------------|--------------|-----------|
| app/service | v1.2.3 | 3/47 | 4 | 2h ago (Trivy) |
### 10.2 Artifact -> Vulnerabilities Tab (Evidence-First)
```
+----------------------------------+-----------------------------------+
| Finding Cards (scrollable) | Explainability Panel |
| | |
| [CVE-2024-1234] CRITICAL | Overview | Reachability | Policy |
| openssl 3.0.14 -> 3.0.15 | |
| [Fix PR] [VEX: Not Affected] | Scanner: Trivy 0.53.0 |
| [Attach Evidence] | DB: 2025-11-27 |
| | Attestation: sha256:2e61... |
| [CVE-2024-5678] HIGH | |
| log4j 2.17.0 | [Why flagged] |
| [VEX: Mitigated] | - version.match: 2.17.0 < 2.17.1 |
| | - gate: severity >= HIGH |
+----------------------------------+-----------------------------------+
```
### 10.3 Policy View
Gate rules (like Anchore) with preview + dry-run; show which triggers cause failure.
### 10.4 Audit
**"Create immutable audit bundle"** -> produces ZIP/OCI artifact with reports, VEX JSON, policy evals, and in-toto/DSSE attestations.
### 10.5 Registry/Admission
"Ready to deploy" badge when all gates met and required attestations verified.
---
## 11. API Endpoints (High-Level)
```text
GET /artifacts
GET /artifacts/{id}/vulnerabilities
GET /vulnerabilities/{id}
POST /vex-decisions
PATCH /vex-decisions/{id}
GET /artifacts/{id}/attestations
POST /audit-bundles
GET /audit-bundles/{bundleId}
```
---
## 12. JSON Schema Locations
The following schemas should be created/maintained:
- `docs/schemas/vex-decision.schema.json` - VEX decision form schema
- `docs/schemas/attestation-vuln-scan.schema.json` - Vulnerability scan attestation
- `docs/schemas/audit-bundle-index.schema.json` - Audit bundle manifest
---
## 13. Related Advisories
- `27-Nov-2025 - Explainability Layer for Vulnerability Verdicts.md` - Evidence chain model
- `27-Nov-2025 - Making Graphs Understandable to Humans.md` - Graph navigation UX
- `25-Nov-2025 - Define Safe VEX 'Not Affected' Claims with Proofs.md` - VEX proof requirements
---
## 14. Sprint Integration
This advisory maps to:
- **SPRINT_0215_0001_0001_vuln_triage_ux.md** (NEW) - UI triage workspace implementation
- **SPRINT_210_ui_ii.md** - VEX tab tasks (UI-LNM-22-003)
- **SPRINT_0334_docs_modules_vuln_explorer.md** - Module documentation updates
---
*Last updated: 2025-11-28*

View File

@@ -64,6 +64,22 @@ These are the authoritative advisories to reference for implementation:
- **Sprint:** Multiple sprints (0186, 0401, 0512)
- **Status:** High-level roadmap document
### Vulnerability Triage UX & VEX-First Decisioning
- **Canonical:** `28-Nov-2025 - Vulnerability Triage UX & VEX-First Decisioning.md`
- **Sprint:** SPRINT_0215_0001_0001_vuln_triage_ux.md (NEW)
- **Related Sprints:**
- SPRINT_210_ui_ii.md (UI-LNM-22-003 VEX tab)
- SPRINT_0334_docs_modules_vuln_explorer.md (docs)
- **Related Advisories:**
- `27-Nov-2025 - Explainability Layer for Vulnerability Verdicts.md` (evidence chain)
- `27-Nov-2025 - Making Graphs Understandable to Humans.md` (graph UX)
- `25-Nov-2025 - Define Safe VEX 'Not Affected' Claims with Proofs.md` (VEX proofs)
- **Status:** New - defines converged triage UX across Snyk/GitLab/Harbor/Anchore patterns
- **Schemas:**
- `docs/schemas/vex-decision.schema.json`
- `docs/schemas/attestation-vuln-scan.schema.json`
- `docs/schemas/audit-bundle-index.schema.json`
## Files to Archive
The following files should be moved to `archived/` as they are superseded:
@@ -95,6 +111,7 @@ The following files should be moved to `archived/` as they are superseded:
| Unknowns Registry | SPRINT_0140_0001_0001 | EXISTING (implemented) |
| Graph Revision IDs | SPRINT_0401_0001_0001 | EXISTING |
| DSSE/Rekor Batching | SPRINT_0401_0001_0001 | EXISTING |
| Vuln Triage UX / VEX | SPRINT_0215_0001_0001 | NEW |
## Implementation Priority
@@ -103,8 +120,9 @@ Based on gap analysis:
1. **P0 - CVSS v4.0** (Sprint 0190) - Industry moving to v4.0, genuine gap
2. **P1 - SPDX 3.0.1** (Sprint 0186 tasks 15a-15f) - Standards compliance
3. **P1 - Public Benchmark** (Sprint 0513) - Differentiation/marketing value
4. **P2 - Explainability** (Sprint 0401) - UX enhancement, existing tasks
5. **P3 - Already Implemented** - Unknowns, Graph IDs, DSSE batching
4. **P1 - Vuln Triage UX** (Sprint 0215) - Industry-aligned UX for competitive parity
5. **P2 - Explainability** (Sprint 0401) - UX enhancement, existing tasks
6. **P3 - Already Implemented** - Unknowns, Graph IDs, DSSE batching
## Implementer Quick Reference
@@ -124,7 +142,10 @@ For each topic, the implementer should read:
| Sbomer | `docs/modules/sbomer/architecture.md` | `src/Sbomer/*/AGENTS.md` |
| Signals | `docs/modules/signals/architecture.md` | `src/Signals/*/AGENTS.md` |
| Attestor | `docs/modules/attestor/architecture.md` | `src/Attestor/*/AGENTS.md` |
| Vuln Explorer | `docs/modules/vuln-explorer/architecture.md` | `src/VulnExplorer/*/AGENTS.md` |
| VEX-Lens | `docs/modules/vex-lens/architecture.md` | `src/Excititor/*/AGENTS.md` |
| UI | `docs/modules/ui/architecture.md` | `src/UI/*/AGENTS.md` |
---
*Index created: 2025-11-27*
*Last updated: 2025-11-27*
*Last updated: 2025-11-28*