consolidation of some of the modules, localization fixes, product advisories work, qa work
This commit is contained in:
35
docs-archived/modules/vuln-explorer/AGENTS.md
Normal file
35
docs-archived/modules/vuln-explorer/AGENTS.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Vulnerability Explorer agent guide
|
||||
|
||||
## Mission
|
||||
Vulnerability Explorer delivers policy-aware triage, investigation, and reporting surfaces for effective findings.
|
||||
|
||||
## Key docs
|
||||
- [Module README](./README.md)
|
||||
- [Architecture](./architecture.md)
|
||||
- [Implementation plan](./implementation_plan.md)
|
||||
- [Task board](./TASKS.md)
|
||||
|
||||
## How to get started
|
||||
1. Review ./architecture.md for ledger schema, workflow states, and export requirements.
|
||||
2. Open sprint file `/docs/implplan/SPRINT_*.md` and locate stories for this component.
|
||||
3. Check ./TASKS.md and update status before/after work.
|
||||
4. Read README/architecture for design context and update as the implementation evolves.
|
||||
|
||||
## Guardrails
|
||||
- Uphold Aggregation-Only Contract boundaries when consuming ingestion data.
|
||||
- Preserve determinism and provenance in all derived outputs.
|
||||
- Document offline/air-gap pathways for any new feature.
|
||||
- Update telemetry/observability assets alongside feature work.
|
||||
|
||||
## Required Reading
|
||||
- `docs/modules/vuln-explorer/README.md`
|
||||
- `docs/modules/vuln-explorer/architecture.md`
|
||||
- `docs/modules/vuln-explorer/implementation_plan.md`
|
||||
- `docs/modules/platform/architecture-overview.md`
|
||||
|
||||
## Working Agreement
|
||||
- 1. Update task status to `DOING`/`DONE` in both correspoding sprint file `/docs/implplan/SPRINT_*.md` and the local `TASKS.md` when you start or finish work.
|
||||
- 2. Review this charter and the Required Reading documents before coding; confirm prerequisites are met.
|
||||
- 3. Keep changes deterministic (stable ordering, timestamps, hashes) and align with offline/air-gap expectations.
|
||||
- 4. Coordinate doc updates, tests, and cross-guild communication whenever contracts or workflows change.
|
||||
- 5. Revert to `TODO` if you pause the task without shipping changes; leave notes in commit/PR descriptions for context.
|
||||
95
docs-archived/modules/vuln-explorer/README.md
Normal file
95
docs-archived/modules/vuln-explorer/README.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# StellaOps Vulnerability Explorer
|
||||
|
||||
Vulnerability Explorer delivers policy-aware triage, investigation, and reporting surfaces for effective findings.
|
||||
|
||||
## Latest updates (2025-11-30)
|
||||
- Documentation refresh aligned to sprint 0334: added observability/runbook snapshot and cross-links to OpenAPI draft (`./api.md`) and schemas in `architecture.md`.
|
||||
- New offline-friendly observability runbook at `runbooks/observability.md` plus stub Grafana JSON in `runbooks/dashboards/`.
|
||||
- Retained 2025-11-03 access-control changes; verify Authority scopes before enabling attachment uploads (`docs/updates/2025-11-03-vuln-explorer-access-controls.md`).
|
||||
|
||||
## Responsibilities
|
||||
- Present policy-evaluated findings with advisory, VEX, SBOM, and runtime context.
|
||||
- Capture triage workflow in an immutable findings ledger with role-based access.
|
||||
- Provide pivots, exports, and reports for auditors and operations teams.
|
||||
- Integrate explain traces, remediation notes, and offline bundles.
|
||||
|
||||
## Key components
|
||||
- Findings Ledger service + API.
|
||||
- Console module and CLI verbs for triage workflows.
|
||||
- Export integrations for reports and evidence packages.
|
||||
|
||||
## Integrations & dependencies
|
||||
- Policy Engine for effective findings streams.
|
||||
- Concelier/Excititor for evidence provenance.
|
||||
- Scheduler for remediation/verification jobs.
|
||||
- Notify for triage notifications.
|
||||
|
||||
## Operational notes
|
||||
- Audit logging per Epic 6 requirements.
|
||||
- Offline-ready CSV/PDF exports with deterministic hashes.
|
||||
- Dashboards for MTTR and triage throughput.
|
||||
- Observability runbook and dashboard stub: see `runbooks/observability.md` and `runbooks/dashboards/vuln-explorer-observability.json` (import locally).
|
||||
|
||||
## Implementation Status
|
||||
|
||||
### Phase 1 – Findings Ledger & resolver (In Progress)
|
||||
- Append-only ledger with Merkle root anchoring
|
||||
- Projector to finding_records and finding_history tables
|
||||
- Ecosystem resolvers: npm/Maven/PyPI/Go/RPM/DEB with canonical advisory keys
|
||||
- Provenance hashing and time-travel snapshots
|
||||
- Idempotent event processing
|
||||
|
||||
### Phase 2 – API & simulation (Planned)
|
||||
- REST endpoints: /v1/findings (list/detail/grouping/simulation)
|
||||
- Batch evaluation with Policy Engine rationales
|
||||
- Export orchestrator for JSON/CSV/PDF
|
||||
- Simulation endpoint returning diffs without state mutation
|
||||
|
||||
### Phase 3 – Console & CLI workflows (Planned)
|
||||
- Triage UI: assignments, comments, remediation plans, simulation bar
|
||||
- Detail tabs: policy, evidence, paths, remediation
|
||||
- Keyboard accessibility, virtualization for large result sets
|
||||
- CLI commands: stella vuln list/show/simulate/assign/accept-risk/verify-fix/export
|
||||
|
||||
### Phase 4 – Automation & integrations (Planned)
|
||||
- Advisory AI hints integration
|
||||
- Zastava runtime exposure correlation
|
||||
- Notify rules for SLA breaches and deadlines
|
||||
- Scheduler follow-up scans and Graph Explorer deep links
|
||||
|
||||
### Phase 5 – Exports & offline parity (Planned)
|
||||
- Deterministic bundles: JSON, CSV, PDF formats
|
||||
- Offline Kit manifests with signed reports
|
||||
- Audit logs and compliance exports
|
||||
- Evidence bundle viewer
|
||||
|
||||
### Phase 6 – Observability & hardening (Planned)
|
||||
- Dashboards: projection lag, MTTR, accepted-risk cadence
|
||||
- Alerts: projector backlog, API 5xx, export failures, expiring accepted-risk
|
||||
- Performance tuning for 5M findings/tenant
|
||||
- Security/RBAC validation and attachment encryption
|
||||
|
||||
### Key Acceptance Criteria
|
||||
- Ledger/event sourcing reproduces historical states byte-for-byte with Merkle verification
|
||||
- Resolver respects ecosystem semantics, scope, runtime context
|
||||
- Triage workflows enforce justification/approval with audit records
|
||||
- Simulation returns policy diffs without mutating state; CLI/UI parity achieved
|
||||
- Exports reproducible with signed manifests and provenance
|
||||
- RBAC/ABAC validated; attachments encrypted; tenant isolation guaranteed
|
||||
|
||||
### Technical Decisions & Risks
|
||||
- Advisory identity collisions: strict canonicalization, linkset references, raw evidence access
|
||||
- Resolver inaccuracies: property-based tests, path verification, manual override workflows
|
||||
- Projection lag/backlog: autoscaling, queue backpressure, alerting, pause controls
|
||||
- Export size/performance: streaming NDJSON, size estimators, chunked downloads
|
||||
- User confusion on suppression: rationale tab, explicit badges, explain traces
|
||||
|
||||
### Operational Assets (Sprint 0334 · 2025-11-30)
|
||||
- Observability runbook: runbooks/observability.md
|
||||
- Dashboard stub: runbooks/dashboards/vuln-explorer-observability.json
|
||||
- OpenAPI draft: api.md and openapi/vuln-explorer.v1.yaml
|
||||
- Access controls: docs/updates/2025-11-03-vuln-explorer-access-controls.md
|
||||
|
||||
## Epic alignment
|
||||
- Epic 6: Vulnerability Explorer.
|
||||
- VULN stories tracked in ../../TASKS.md and src/VulnExplorer/**/TASKS.md.
|
||||
@@ -0,0 +1,96 @@
|
||||
# Vulnerability Explorer and Findings Ledger (Guide)
|
||||
|
||||
The Vulnerability Explorer is the StellaOps interface for vulnerability triage and remediation planning. It brings together SBOM facts, advisory/VEX evidence, reachability signals, and policy explanations into a single, auditable workflow.
|
||||
|
||||
This guide is intentionally conceptual. Concrete schemas, identifiers, and endpoint shapes are defined in the module dossiers and schema files.
|
||||
|
||||
## Core Objects
|
||||
|
||||
- **Finding record:** the current, enriched view of a vulnerability for a specific artifact/context (tenant, image digest/artifact id, policy version).
|
||||
- **Finding history:** append-only state transitions (who/what changed status and why), suitable for audit replay.
|
||||
- **Triage actions:** discrete operator actions (assignment, comment, mitigation note, ticket link, exception request) with provenance.
|
||||
- **Evidence references:** stable pointers to SBOM slices, advisory observations, VEX observations/linksets, reachability proofs, and attestation bundles.
|
||||
|
||||
## Triage UX Contract (Console)
|
||||
|
||||
Every triage surface should answer, in order:
|
||||
|
||||
1. Can I ship this?
|
||||
2. If not, what exactly blocks me?
|
||||
3. What's the minimum safe change to unblock?
|
||||
|
||||
Key expectations:
|
||||
|
||||
- **Narrative-first:** the default view for a finding is a case-style summary ("why") plus a visible evidence rail.
|
||||
- **Proof-linking is mandatory:** every chip/badge/assertion links to the evidence objects that justify it.
|
||||
- **Quiet by default, never silent:** muted/non-actionable lanes are hidden by default but surfaced via counts and toggles; muting never deletes evidence.
|
||||
- **Replayable:** the UI should support exporting a deterministic evidence bundle for offline/audit verification.
|
||||
|
||||
## Workflow (Operator View)
|
||||
|
||||
1. Start from a finding list filtered to the relevant tenant and time window.
|
||||
2. Open a finding to review:
|
||||
- Policy outcome (block/ship/needs exception)
|
||||
- Effective VEX status (and the underlying issuer evidence)
|
||||
- Reachability/impact signals (where available)
|
||||
- Advisory provenance and conflicts
|
||||
3. Record a triage action (assign, comment, request exception) with justification.
|
||||
4. Export an evidence bundle when review, escalation, or offline verification is required.
|
||||
|
||||
The default posture is VEX-first: VEX evidence and issuer trust are treated as first-class inputs to decisioning and explainability.
|
||||
|
||||
## Lanes and Signed Decisions
|
||||
|
||||
Most UIs need "lanes" (visibility buckets) derived from deterministic risk and operator decisions. Common examples:
|
||||
|
||||
- `ACTIVE`
|
||||
- `BLOCKED`
|
||||
- `NEEDS_EXCEPTION`
|
||||
- `MUTED_REACH` (not reachable)
|
||||
- `MUTED_VEX` (effective VEX is not_affected)
|
||||
- `COMPENSATED` (controls satisfy policy)
|
||||
|
||||
Decisions that change visibility or gating should be:
|
||||
|
||||
- Signed and auditable (who did what, when, and why).
|
||||
- Append-only (revoke/expire instead of delete).
|
||||
- Linked to the policy and evidence that justified the change.
|
||||
|
||||
## Smart-Diff History
|
||||
|
||||
The Explorer should make meaningful changes obvious:
|
||||
|
||||
- Maintain immutable snapshots of inputs/outputs for each finding.
|
||||
- Highlight meaningful changes (verdict/lane changes, threshold crossings, reachability changes, effective VEX changes).
|
||||
- Keep "details" available without overwhelming the default view.
|
||||
|
||||
## Determinism, Integrity, and Replay
|
||||
|
||||
The Explorer is designed to be replayable and tamper-evident:
|
||||
|
||||
- History and actions are append-only.
|
||||
- Exports use deterministic ordering and UTC timestamps.
|
||||
- Evidence bundles carry hashes/manifests so a third party can verify integrity without trusting a live service.
|
||||
- When Merkle anchoring is enabled, exports can include roots and inclusion proofs for additional tamper evidence.
|
||||
|
||||
## Offline / Air-Gap Operation
|
||||
|
||||
- Explorer workflows must work against Offline Kit snapshots when running in sealed environments.
|
||||
- The Console should surface snapshot identity and staleness (feeds, VEX, policy versions) rather than hiding it.
|
||||
- Export bundles are the primary bridge between online and offline review.
|
||||
|
||||
## Integration Points
|
||||
|
||||
- **Console UI:** findings list + triage case view; evidence drawers; export/download flows.
|
||||
- **Policy engine:** produces explainability traces and gates actions (for example, exception workflows).
|
||||
- **Graph/Reachability:** overlays and evidence slices for reachable vs not reachable decisions where available.
|
||||
- **VEX Lens / Excititor:** issuer trust, provenance, linksets, and effective status (see `docs/VEX_CONSENSUS_GUIDE.md`).
|
||||
|
||||
## Related Docs
|
||||
|
||||
- `docs/UI_GUIDE.md`
|
||||
- `docs/VEX_CONSENSUS_GUIDE.md`
|
||||
- `docs/modules/vuln-explorer/architecture.md`
|
||||
- `docs/modules/findings-ledger/schema.md`
|
||||
- `docs/modules/findings-ledger/merkle-anchor-policy.md`
|
||||
- `docs/ARCHITECTURE_OVERVIEW.md`
|
||||
7
docs-archived/modules/vuln-explorer/api.md
Normal file
7
docs-archived/modules/vuln-explorer/api.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Vuln Explorer API – draft v1 (2025-11-25)
|
||||
|
||||
- OpenAPI: `docs/modules/vuln-explorer/openapi/vuln-explorer.v1.yaml`
|
||||
- Scope: read-only vulnerability listing/detail for Console/CLI; deterministic ordering (score desc, id asc) with opaque page tokens.
|
||||
- Required headers: `x-stella-tenant`; optional `policyVersion`.
|
||||
- Filters: CVE, PURL, severity band, exploitability flag, fixAvailable.
|
||||
- Responses include policyVersion + rationaleId for explainability; provenance anchors back to Findings Ledger/evidence bundles.
|
||||
199
docs-archived/modules/vuln-explorer/architecture.md
Normal file
199
docs-archived/modules/vuln-explorer/architecture.md
Normal file
@@ -0,0 +1,199 @@
|
||||
# Vulnerability Explorer architecture
|
||||
|
||||
> Based on Epic 6 – Vulnerability Explorer; this specification summarises the ledger model, triage workflows, APIs, and export requirements.
|
||||
|
||||
## 1) Ledger data model
|
||||
|
||||
- See [`../findings-ledger/schema.md`](../findings-ledger/schema.md) for the canonical SQL schema, hashing strategy, and fixtures underpinning these collections.
|
||||
|
||||
- **Collections / tables**
|
||||
- `finding_records` – canonical, policy-derived findings enriched with advisory, VEX, SBOM, runtime context. Includes `policyVersion`, `advisoryRawIds`, `vexRawIds`, `sbomComponentId`, `policyRationale` (array of explain bundle URIs or remediation notes returned by `/api/policy/eval/batch`), and `explainBundleRef`.
|
||||
- `finding_history` – append-only state transitions (`new`, `triaged`, `accepted_risk`, `remediated`, `false_positive`, etc.) with timestamps, actor, and justification.
|
||||
- `triage_actions` – discrete operator actions (comment, assignment, remediation note, ticket link) with immutable provenance.
|
||||
- `remediation_plans` – structured remediation steps (affected assets, deadlines, recommended fixes, auto-generated from SRM/AI hints).
|
||||
- `reports` – saved report definitions, export manifests, and signatures.
|
||||
|
||||
- **Immutability & provenance** – All updates are append-only; previous state is recoverable. Records capture `tenant`, `artifactId`, `findingKey`, `policyVersion`, `sourceRunId`, `sr mDigest`.
|
||||
|
||||
## 2) Triage workflow
|
||||
|
||||
1. **Ingest effective findings** from Policy Engine (stream `policy.finding.delta`) and on-demand batch evaluations. Projection workers call `/api/policy/eval/batch` with ledger event payloads to receive status/severity/label/rationale updates before writing `finding_records`. Each delta updates `finding_records`, generates history entries, and triggers notification rules.
|
||||
2. **Prioritisation** uses contextual heuristics: runtime exposure, VEX status, policy severity, AI hints. Stored as `priorityScore` with provenance from Zastava/AI modules.
|
||||
3. **Assignment & collaboration** – Operators claim findings, add comments, attach evidence, and link tickets. Assignment uses Authority identities and RBAC.
|
||||
4. **Remediation tracking** – Link remediation plans, record progress, and integrate with Scheduler for follow-up scans once fixes deploy.
|
||||
5. **Closure** – When Policy or rescans mark finding resolved, system logs closure with explain trace and updates audit ledger.
|
||||
|
||||
State machine summary:
|
||||
|
||||
```
|
||||
new -> (triage) triaged -> (remediate) in_progress -> (verify) awaiting_verification -> (scan) remediated
|
||||
new -> (false_positive) closed_false_positive
|
||||
new -> (risk_accept) accepted_risk
|
||||
```
|
||||
|
||||
All transitions require justification; certain transitions (accepted risk) require multi-approver workflow defined by Policy Studio.
|
||||
|
||||
## 3) APIs
|
||||
|
||||
- `GET /v1/findings` — filtered listing with pagination, search (artifact, advisory, priority, status, assignee).
|
||||
- `GET /v1/findings/{id}` — detail view (policy context, explain trace, evidence timeline).
|
||||
- `POST /v1/findings/{id}/actions` — create triage action (assign, comment, status change, remediation, ticket link) with DSSE signature support.
|
||||
- `POST /v1/reports` — generate report artifact (JSON, CSV, PDF) defined by saved templates; records manifest + signature.
|
||||
- `GET /v1/exports/offline` — stream deterministic bundle for Offline Kit (findings JSON, history, attachments, manifest).
|
||||
|
||||
CLI mirrors these endpoints (`stella findings list|view|update|export`). Console UI consumes the same APIs via typed clients.
|
||||
|
||||
## 4) AI/automation integration
|
||||
|
||||
- Advisory AI contributes remediation hints and conflict explanations stored alongside findings (`aiInsights`).
|
||||
- Scheduler integration triggers follow-up scans or policy re-evaluation when remediation plan reaches checkpoint.
|
||||
- Zastava (Differential SBOM) feeds runtime exposure signals to reprioritise findings automatically.
|
||||
|
||||
## 5) Observability & compliance
|
||||
|
||||
- Metrics: `findings_open_total{severity,tenant}`, `findings_mttr_seconds`, `triage_actions_total{type}`, `report_generation_seconds`.
|
||||
- Logs: structured with `findingId`, `artifactId`, `advisory`, `policyVersion`, `actor`, `actionType`.
|
||||
- Audit exports: `audit_log.jsonl` appended whenever state changes; offline bundles include signed audit log and manifest.
|
||||
- Compliance: accepted risk requires dual approval and stores justification plus expiry reminders (raised through Notify).
|
||||
- Runbook and dashboard stub for demo snapshot: `runbooks/observability.md` and `runbooks/dashboards/vuln-explorer-observability.json` (offline import).
|
||||
|
||||
## 6) Identity & access integration
|
||||
|
||||
- **Scopes** – `vuln:view`, `vuln:investigate`, `vuln:operate`, `vuln:audit` map to read-only, triage, workflow, and audit experiences respectively. The deprecated `vuln:read` scope is still honoured for legacy tokens but is no longer advertised.
|
||||
- **Attribute filters (ABAC)** – Authority enforces per-service-account filters via the client-credential parameters `vuln_env`, `vuln_owner`, and `vuln_business_tier`. Service accounts define the allowed values in `authority.yaml` (`attributes` block). Tokens include the resolved filters as claims (`stellaops:vuln_env`, `stellaops:vuln_owner`, `stellaops:vuln_business_tier`), and tokens persisted to PostgreSQL retain the same values for audit and revocation.
|
||||
- **Audit trail** – Every token issuance emits `authority.vuln_attr.*` audit properties that mirror the resolved filter set, along with `delegation.service_account` and ordered `delegation.actor[n]` entries so Vuln Explorer can correlate access decisions.
|
||||
- **Permalinks** – Signed permalinks inherit the caller’s ABAC filters; consuming services must enforce the embedded claims in addition to scope checks when resolving permalinks.
|
||||
- **Attachment tokens** – Authority mints short-lived tokens (`POST /vuln/attachments/tokens/issue`) to gate evidence downloads. Verification (`POST /vuln/attachments/tokens/verify`) enforces tenant, scope, and ABAC metadata, and emits `vuln.attachment.token.*` audit records.
|
||||
- **Ledger verification** – Offline workflows validate attachments by comparing the Authority-issued token, the Vuln Explorer ledger hash, and the downloaded artefact hash before distribution.
|
||||
|
||||
## 7) Offline bundle requirements
|
||||
|
||||
- Bundle structure:
|
||||
- `manifest.json` (hashes, counts, policy version, generation timestamp).
|
||||
- `findings.jsonl` (current open findings).
|
||||
- `history.jsonl` (state changes).
|
||||
- `actions.jsonl` (comments, assignments, tickets).
|
||||
- `reports/` (generated PDFs/CSVs).
|
||||
- `signatures/` (DSSE envelopes).
|
||||
- Bundles produced deterministically; Export Center consumes them for mirror profiles.
|
||||
|
||||
## 8) VEX-First Triage UX
|
||||
|
||||
> Reference: Product advisory `docs/product/advisories/archived/27-Nov-2025-superseded/28-Nov-2025 - Vulnerability Triage UX & VEX-First Decisioning.md`
|
||||
|
||||
### 8.1 Evidence-First Finding Cards
|
||||
|
||||
Each vulnerability finding is displayed as an evidence-first card showing:
|
||||
- CVE/vulnerability identifier with severity badge
|
||||
- Package name, version, ecosystem
|
||||
- Location (file path, container layer, function, call path)
|
||||
- Scanner and database date
|
||||
- Status badges: `New`, `VEX: Not affected`, `Policy: blocked`
|
||||
|
||||
Primary actions per card:
|
||||
- **VEX: Set status** - Opens VEX decision modal
|
||||
- **Fix PR / View Fix** - When available from connected scanners (Snyk/GitLab)
|
||||
- **Attach Evidence** - Link PRs, tickets, docs, commits
|
||||
- **Copy audit reference** - findingId + attestation digest
|
||||
|
||||
### 8.2 VEX Decision Model
|
||||
|
||||
VEX decisions follow the `VexDecision` schema (`docs/modules/vuln-explorer/schemas/vex-decision.schema.json`):
|
||||
|
||||
**Status values:**
|
||||
- `NOT_AFFECTED` - Vulnerability does not apply to this artifact
|
||||
- `AFFECTED_MITIGATED` - Vulnerable but mitigations in place
|
||||
- `AFFECTED_UNMITIGATED` - Vulnerable without mitigations
|
||||
- `FIXED` - Vulnerability has been remediated
|
||||
|
||||
**Justification types (CSAF/VEX aligned):**
|
||||
- `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`
|
||||
|
||||
**Scope and validity:**
|
||||
- Decisions can be scoped to specific environments and projects
|
||||
- Validity windows with `notBefore` and `notAfter` timestamps
|
||||
- Expired decisions are surfaced with warnings
|
||||
|
||||
### 8.3 Explainability Panel
|
||||
|
||||
Right-side panel with tabs for each finding:
|
||||
|
||||
**Overview tab:**
|
||||
- Title, severity, package/version
|
||||
- Scanner + DB date
|
||||
- Finding history timeline
|
||||
- Current VEX decision summary
|
||||
|
||||
**Reachability tab:**
|
||||
- Call path visualization
|
||||
- Module dependency list
|
||||
- Runtime usage indicators (when available)
|
||||
|
||||
**Policy tab:**
|
||||
- Policy evaluation result (PASS/WARN/FAIL)
|
||||
- Gate details with "this gate failed because..." explanations
|
||||
- Links to gate definitions
|
||||
|
||||
**Attestations tab:**
|
||||
- Attestations mentioning this artifact/vulnerability/scan
|
||||
- Type, subject, predicate, signer, verified status
|
||||
- "Signed evidence" pill linking to attestation detail
|
||||
|
||||
### 8.4 VEX Decision APIs
|
||||
|
||||
New endpoints for VEX decisions:
|
||||
|
||||
- `POST /v1/vex-decisions` - Create new VEX decision with optional attestation
|
||||
- `PATCH /v1/vex-decisions/{id}` - Update existing decision (creates superseding record)
|
||||
- `GET /v1/vex-decisions` - List decisions with filters
|
||||
- `GET /v1/vex-decisions/{id}` - Get decision detail
|
||||
|
||||
Request/response follows `VexDecisionDto` per schema.
|
||||
|
||||
### 8.5 Audit Bundle Export
|
||||
|
||||
Immutable audit bundles follow the `AuditBundleIndex` schema (`docs/modules/evidence-locker/schemas/audit-bundle-index.schema.json`):
|
||||
|
||||
**Bundle contents:**
|
||||
- Vulnerability reports (scanner outputs)
|
||||
- SBOM (CycloneDX/SPDX)
|
||||
- VEX decisions
|
||||
- Policy evaluations
|
||||
- Raw attestations (DSSE envelopes)
|
||||
- `audit-bundle-index.json` manifest with integrity hashes
|
||||
|
||||
**APIs:**
|
||||
- `POST /v1/audit-bundles` - Create new bundle (async generation)
|
||||
- `GET /v1/audit-bundles/{bundleId}` - Download bundle (ZIP or OCI)
|
||||
- `GET /v1/audit-bundles` - List previously created bundles
|
||||
|
||||
`GET /v1/audit-bundles/{bundleId}` may use content negotiation: `Accept: application/json` returns job metadata; `Accept: application/octet-stream` streams bundle bytes.
|
||||
|
||||
### 8.6 Industry Pattern Alignment
|
||||
|
||||
The triage UX aligns with industry patterns from:
|
||||
|
||||
| Tool | Pattern Adopted |
|
||||
|------|-----------------|
|
||||
| **Snyk** | PR checks, Fix PRs, ignore with reasons |
|
||||
| **GitLab SCA** | Vulnerability Report, status workflow, activity log |
|
||||
| **Harbor/Trivy** | Artifact-centric navigation, attestation accessories |
|
||||
| **Anchore** | Policy gates with trigger explanations, allowlists |
|
||||
|
||||
## 9) Schemas
|
||||
|
||||
The following JSON schemas define the data contracts for VEX and audit functionality:
|
||||
|
||||
- `docs/modules/vuln-explorer/schemas/vex-decision.schema.json` - VEX decision form and persistence
|
||||
- `docs/modules/attestor/schemas/attestation-vuln-scan.schema.json` - Vulnerability scan attestation predicate
|
||||
- `docs/modules/evidence-locker/schemas/audit-bundle-index.schema.json` - Audit bundle manifest
|
||||
|
||||
These schemas are referenced by both backend DTOs and frontend TypeScript interfaces.
|
||||
@@ -0,0 +1,51 @@
|
||||
# Triage
|
||||
|
||||
**Status:** Design/Planning
|
||||
**Source:** N/A (cross-cutting concept)
|
||||
**Owner:** VulnExplorer Guild
|
||||
|
||||
## Purpose
|
||||
|
||||
Triage defines workflows and data structures for vulnerability triage, exploit path analysis, and proof bundle generation. Provides specifications for prioritization, evidence review, and decision capture used by VulnExplorer and Policy modules.
|
||||
|
||||
## Components
|
||||
|
||||
**Concept Documentation:**
|
||||
- `exploit-path-inbox.md` - Exploit path inbox specification for automated triage
|
||||
- `proof-bundle-spec.md` - Proof bundle format for evidence packaging
|
||||
|
||||
**Triage Workflows:**
|
||||
- Automated triage (Signals-based prioritization)
|
||||
- Manual triage (human review and decision)
|
||||
- Exploit path analysis (reachability to exploitable sinks)
|
||||
- Proof bundle generation (evidence packaging for decisions)
|
||||
|
||||
## Implementation Locations
|
||||
|
||||
Triage functionality is implemented across multiple modules:
|
||||
- **VulnExplorer** - Triage UI and workflow orchestration
|
||||
- **Signals** - Automated prioritization scoring
|
||||
- **Policy Engine** - Exploit path analysis
|
||||
- **EvidenceLocker** - Proof bundle storage
|
||||
- **Notify** - Triage alert distribution
|
||||
|
||||
## Dependencies
|
||||
|
||||
- VulnExplorer (triage UI)
|
||||
- Signals (prioritization)
|
||||
- Policy Engine (exploit paths)
|
||||
- EvidenceLocker (proof bundles)
|
||||
- Notify (alerts)
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- Exploit Path Inbox: `./exploit-path-inbox.md`
|
||||
- Proof Bundle Spec: `./proof-bundle-spec.md`
|
||||
- VulnExplorer: `../vuln-explorer/`
|
||||
- Signals: `../signals/`
|
||||
- Policy: `../policy/`
|
||||
- EvidenceLocker: `../evidence-locker/`
|
||||
|
||||
## Current Status
|
||||
|
||||
Triage workflows documented in exploit-path-inbox.md and proof-bundle-spec.md. Implementation distributed across VulnExplorer (UI/workflows), Signals (scoring), Policy (analysis), and EvidenceLocker (proof storage) modules.
|
||||
@@ -0,0 +1,176 @@
|
||||
# Exploit Path Inbox Architecture
|
||||
|
||||
## Overview
|
||||
|
||||
The Exploit Path Inbox provides a triage workflow that groups vulnerabilities by their complete attack chain rather than individual CVEs. This enables analysts to assess and remediate entire exploit paths at once, improving efficiency and ensuring comprehensive coverage.
|
||||
|
||||
## Key Concepts
|
||||
|
||||
### Exploit Path
|
||||
|
||||
An **Exploit Path** represents the complete chain from an entry point to a vulnerable symbol:
|
||||
|
||||
```
|
||||
Artifact → Package → Vulnerable Symbol → Entry Point
|
||||
```
|
||||
|
||||
For example:
|
||||
```
|
||||
sha256:abc... → pkg:npm/lodash@4.17.19 → _.template() → /api/render
|
||||
```
|
||||
|
||||
### Path ID Generation
|
||||
|
||||
Path IDs are deterministic hashes ensuring stable references:
|
||||
|
||||
```
|
||||
PathId = SHA256(artifactDigest | packagePurl | symbolName | entryPointName)
|
||||
```
|
||||
|
||||
This allows:
|
||||
- Consistent tracking across scans
|
||||
- Stable exception targeting
|
||||
- Reproducible audits
|
||||
|
||||
### Grouping Logic
|
||||
|
||||
Findings are grouped into exploit paths based on:
|
||||
|
||||
1. **Reachability Graph**: If reachability data exists, group by actual call paths
|
||||
2. **Fallback**: If no reachability, group by package only
|
||||
|
||||
## Data Model
|
||||
|
||||
### ExploitPath
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `pathId` | string | Stable deterministic identifier |
|
||||
| `artifactDigest` | string | Container image digest |
|
||||
| `package` | PackageRef | Package containing vulnerability |
|
||||
| `symbol` | VulnerableSymbol | Vulnerable function/method |
|
||||
| `entryPoint` | EntryPoint | Entry point exposing the path |
|
||||
| `cveIds` | string[] | All CVEs affecting this path |
|
||||
| `reachability` | ReachabilityStatus | Reachability lattice state |
|
||||
| `riskScore` | PathRiskScore | Aggregated risk metrics |
|
||||
| `evidence` | PathEvidence | Supporting evidence |
|
||||
| `activeExceptions` | ExceptionRef[] | Active suppressions |
|
||||
| `isQuiet` | boolean | Whether path is suppressed |
|
||||
|
||||
### ReachabilityStatus
|
||||
|
||||
| State | Description |
|
||||
|-------|-------------|
|
||||
| `Unknown` | No reachability analysis performed |
|
||||
| `StaticallyReachable` | Static analysis found a path |
|
||||
| `RuntimeConfirmed` | Runtime observation confirmed reachability |
|
||||
| `Unreachable` | Confirmed not reachable |
|
||||
| `Contested` | Conflicting evidence |
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### GET /triage/inbox
|
||||
|
||||
Returns exploit paths for a given scope.
|
||||
|
||||
**Query Parameters:**
|
||||
- `artifactDigest` (string): Filter by artifact
|
||||
- `environment` (string): Filter by environment
|
||||
- `quiet` (boolean): Filter by suppression status
|
||||
- `minCvss` (number): Minimum CVSS score
|
||||
- `reachability` (string): Filter by reachability status
|
||||
- `offset` (number): Pagination offset
|
||||
- `limit` (number): Page size (default 50)
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"paths": [...],
|
||||
"totalCount": 42,
|
||||
"quietCount": 12,
|
||||
"activeCount": 30,
|
||||
"offset": 0,
|
||||
"limit": 50
|
||||
}
|
||||
```
|
||||
|
||||
### GET /triage/paths/{pathId}
|
||||
|
||||
Returns detailed exploit path information.
|
||||
|
||||
### GET /triage/paths/{pathId}/proof
|
||||
|
||||
Returns proof bundle (see proof-bundle-spec.md).
|
||||
|
||||
## UI Components
|
||||
|
||||
### Three-Pane Layout
|
||||
|
||||
1. **Left Pane (Path List)**
|
||||
- Exploit paths sorted by risk
|
||||
- Quiet/Active toggle
|
||||
- Search by CVE, package, symbol
|
||||
- Risk score badges
|
||||
|
||||
2. **Center Pane (Path Detail)**
|
||||
- CVE list with scores
|
||||
- Package and symbol info
|
||||
- Entry point context
|
||||
- Active exceptions
|
||||
- "Create Exception" button
|
||||
|
||||
3. **Right Pane (Proof Viewer)**
|
||||
- Reach subgraph visualization
|
||||
- Symbol map with source links
|
||||
- VEX claims with trust badges
|
||||
- "Export Proof" button
|
||||
|
||||
## Integration Points
|
||||
|
||||
### Exception System
|
||||
|
||||
Exceptions can target exploit paths via `pathId`:
|
||||
```yaml
|
||||
scope:
|
||||
pathId: "path:abc123..."
|
||||
```
|
||||
|
||||
This suppresses all CVEs in the path at once.
|
||||
|
||||
### Build Gates
|
||||
|
||||
Build gates can query by exploit path reachability:
|
||||
```yaml
|
||||
gates:
|
||||
- name: block-reachable-critical
|
||||
condition: reachability == "RuntimeConfirmed" && severity == "Critical"
|
||||
action: block
|
||||
```
|
||||
|
||||
### VEX Generation
|
||||
|
||||
VEX statements can reference exploit paths for context:
|
||||
```json
|
||||
{
|
||||
"vulnerability": "CVE-2024-1234",
|
||||
"product": "sha256:abc...",
|
||||
"status": "not_affected",
|
||||
"justification": "vulnerable_code_not_in_execute_path",
|
||||
"context": {
|
||||
"exploitPathId": "path:abc123..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Triage by Path**: Address entire exploit paths, not individual CVEs
|
||||
2. **Use Reachability**: Prioritize runtime-confirmed paths
|
||||
3. **Document Evidence**: Attach proof bundles to exceptions
|
||||
4. **Regular Review**: Re-evaluate paths when reachability changes
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Proof Bundle Specification](./proof-bundle-spec.md)
|
||||
- [Recheck Policy](../policy/recheck-policy.md)
|
||||
- [Evidence Hooks](../policy/evidence-hooks.md)
|
||||
@@ -0,0 +1,235 @@
|
||||
# Proof Bundle Specification
|
||||
|
||||
## Overview
|
||||
|
||||
A **Proof Bundle** aggregates all evidence supporting an exploit path assessment. It provides a complete, self-contained package for audit, compliance, and decision-making.
|
||||
|
||||
## Bundle Contents
|
||||
|
||||
### 1. Reach Subgraph
|
||||
|
||||
The reachability subgraph shows the call path from entry point to vulnerable symbol.
|
||||
|
||||
```json
|
||||
{
|
||||
"nodes": [
|
||||
{
|
||||
"id": "node-001",
|
||||
"label": "handleRequest",
|
||||
"type": "entryPoint",
|
||||
"depth": 0,
|
||||
"isVulnerable": false,
|
||||
"isEntryPoint": true
|
||||
},
|
||||
{
|
||||
"id": "node-002",
|
||||
"label": "renderTemplate",
|
||||
"type": "function",
|
||||
"depth": 1,
|
||||
"isVulnerable": false,
|
||||
"isEntryPoint": false
|
||||
},
|
||||
{
|
||||
"id": "node-003",
|
||||
"label": "_.template",
|
||||
"type": "vulnerableSymbol",
|
||||
"depth": 2,
|
||||
"isVulnerable": true,
|
||||
"isEntryPoint": false
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"sourceId": "node-001",
|
||||
"targetId": "node-002",
|
||||
"label": "calls",
|
||||
"weight": 0.95
|
||||
},
|
||||
{
|
||||
"sourceId": "node-002",
|
||||
"targetId": "node-003",
|
||||
"label": "calls",
|
||||
"weight": 0.90
|
||||
}
|
||||
],
|
||||
"entryPointId": "node-001",
|
||||
"vulnerableSymbolId": "node-003",
|
||||
"totalNodes": 3,
|
||||
"totalEdges": 2
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Symbol Map
|
||||
|
||||
Maps symbol identifiers to source code locations.
|
||||
|
||||
```json
|
||||
{
|
||||
"symbols": [
|
||||
{
|
||||
"id": "node-001",
|
||||
"fullyQualifiedName": "src.api.handleRequest",
|
||||
"sourceFile": "src/api/handler.js",
|
||||
"lineNumber": 42,
|
||||
"language": "javascript",
|
||||
"signature": "function handleRequest(req, res)"
|
||||
},
|
||||
{
|
||||
"id": "node-003",
|
||||
"fullyQualifiedName": "lodash.template",
|
||||
"sourceFile": "node_modules/lodash/template.js",
|
||||
"lineNumber": 156,
|
||||
"language": "javascript",
|
||||
"signature": "function template(string, options)"
|
||||
}
|
||||
],
|
||||
"sourceFiles": [
|
||||
"src/api/handler.js",
|
||||
"node_modules/lodash/template.js"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 3. VEX Claims
|
||||
|
||||
VEX statements from various sources with trust scores.
|
||||
|
||||
```json
|
||||
{
|
||||
"vexClaims": [
|
||||
{
|
||||
"cveId": "CVE-2024-1234",
|
||||
"status": "not_affected",
|
||||
"justification": "vulnerable_code_not_in_execute_path",
|
||||
"source": "vendor:lodash",
|
||||
"trustScore": 0.95,
|
||||
"timestamp": "2024-12-22T10:00:00Z",
|
||||
"signatureValid": true
|
||||
},
|
||||
{
|
||||
"cveId": "CVE-2024-1234",
|
||||
"status": "affected",
|
||||
"justification": null,
|
||||
"source": "nvd",
|
||||
"trustScore": 0.80,
|
||||
"timestamp": "2024-12-20T08:00:00Z",
|
||||
"signatureValid": false
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Trust Scores
|
||||
|
||||
Aggregated confidence metrics.
|
||||
|
||||
```json
|
||||
{
|
||||
"trustScores": {
|
||||
"reachabilityConfidence": 0.90,
|
||||
"vexConfidence": 0.85,
|
||||
"overallConfidence": 0.875,
|
||||
"evidenceCount": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API Endpoint
|
||||
|
||||
### GET /triage/paths/{pathId}/proof
|
||||
|
||||
Returns the complete proof bundle.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"pathId": "path:abc123...",
|
||||
"generatedAt": "2024-12-22T12:00:00Z",
|
||||
"reachSubgraph": { ... },
|
||||
"symbolMap": { ... },
|
||||
"vexClaims": [ ... ],
|
||||
"trustScores": { ... },
|
||||
"bundleDigest": "sha256:def456..."
|
||||
}
|
||||
```
|
||||
|
||||
### GET /triage/paths/{pathId}/proof/export
|
||||
|
||||
Returns proof bundle as downloadable JSON file.
|
||||
|
||||
## Bundle Integrity
|
||||
|
||||
Each bundle includes a digest for integrity verification:
|
||||
|
||||
```
|
||||
bundleDigest = SHA256(canonical_json(bundle_without_digest))
|
||||
```
|
||||
|
||||
This allows:
|
||||
- Tamper detection
|
||||
- Audit trail verification
|
||||
- Reproducible exports
|
||||
|
||||
## Visualization
|
||||
|
||||
### Reach Graph Rendering
|
||||
|
||||
Use Cytoscape.js or similar for interactive visualization:
|
||||
- Nodes colored by type (entry point, intermediate, vulnerable)
|
||||
- Edge width indicates confidence weight
|
||||
- Collapsible for large graphs
|
||||
|
||||
### Symbol Navigation
|
||||
|
||||
Click-through from symbols to source code:
|
||||
- IDE integration (VS Code, JetBrains)
|
||||
- GitHub/GitLab links
|
||||
- Line number highlighting
|
||||
|
||||
### VEX Claim Comparison
|
||||
|
||||
Side-by-side view of conflicting VEX statements:
|
||||
- Trust score comparison
|
||||
- Timestamp ordering
|
||||
- Signature verification badges
|
||||
|
||||
## Use Cases
|
||||
|
||||
### Exception Creation
|
||||
|
||||
When creating an exception, attach proof bundle:
|
||||
```yaml
|
||||
exception:
|
||||
pathId: "path:abc123..."
|
||||
proofBundleDigest: "sha256:def456..."
|
||||
evidence:
|
||||
- type: proof-bundle
|
||||
reference: "/triage/paths/path:abc123.../proof"
|
||||
```
|
||||
|
||||
### Compliance Audit
|
||||
|
||||
Export proof bundles for compliance documentation:
|
||||
1. Query all active exceptions
|
||||
2. Export proof bundle for each
|
||||
3. Generate PDF report with embedded evidence
|
||||
|
||||
### Dispute Resolution
|
||||
|
||||
When VEX claims conflict:
|
||||
1. View all claims in proof bundle
|
||||
2. Compare trust scores and timestamps
|
||||
3. Document resolution rationale
|
||||
|
||||
## Schema Validation
|
||||
|
||||
Proof bundles must validate against JSON Schema:
|
||||
```
|
||||
$id: https://stellaops.io/schemas/proof-bundle/v1
|
||||
```
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Exploit Path Inbox](./exploit-path-inbox.md)
|
||||
- [VEX Trust Scoring](../excititor/scoring.md)
|
||||
- [Reachability Analysis](../scanner/operations/entrypoint.md)
|
||||
@@ -0,0 +1,25 @@
|
||||
# Vulnerability Explorer Overview (Detailed)
|
||||
|
||||
The Vulnerability Explorer is the evidence-linked triage surface that brings together SBOM facts, advisory/VEX evidence, reachability signals, policy explainability, and operator decisions into a single auditable workflow.
|
||||
|
||||
This document complements the high-level guide `docs/VULNERABILITY_EXPLORER_GUIDE.md` with additional detail and cross-links.
|
||||
|
||||
## Core Objects
|
||||
|
||||
- **Finding record:** the current enriched view of a vulnerability for a specific artifact/context (tenant, artifact/image digest, policy version).
|
||||
- **History:** append-only state transitions suitable for audit and replay.
|
||||
- **Triage actions:** operator actions (assignment, comment, mitigation note, exception request) with provenance.
|
||||
- **Evidence references:** stable pointers to evidence objects (SBOM slices, VEX observations/linksets, reachability proofs, explain traces, attestations).
|
||||
|
||||
## Key Properties
|
||||
|
||||
- **Narrative-first:** default view answers “Can I ship? If not, why? What’s the smallest safe change?”
|
||||
- **Proof-linked:** every important fact links to evidence (no “trust the UI”).
|
||||
- **Quiet by default, never silent:** suppression/muting is reversible and auditable.
|
||||
- **Offline-ready:** evidence bundles are verifiable without online lookups.
|
||||
|
||||
## References
|
||||
|
||||
- High-level guide: `docs/VULNERABILITY_EXPLORER_GUIDE.md`
|
||||
- Console operator guide: `docs/UI_GUIDE.md`
|
||||
- Module dossier: `docs/modules/vuln-explorer/architecture.md`
|
||||
@@ -0,0 +1,32 @@
|
||||
# Vulnerability Explorer Using the Console
|
||||
|
||||
This document describes the operator workflow for triaging findings in the Console. It is intentionally evidence-first and audit-oriented.
|
||||
|
||||
## Workflow (Typical)
|
||||
|
||||
1. Start from the findings list filtered to the tenant/environment you care about.
|
||||
2. Open a finding to review:
|
||||
- Verdict and “why” summary
|
||||
- Effective VEX status and issuer provenance
|
||||
- Reachability/impact signals (when available)
|
||||
- Policy gate and explain trace
|
||||
3. Record a triage action (assign/comment/mitigation/exception) with justification.
|
||||
4. Export an evidence bundle when review, escalation, or offline verification is required.
|
||||
|
||||
## What to Expect in a Finding View
|
||||
|
||||
- Clear tenant context and artifact identifiers
|
||||
- Evidence rail (SBOM, VEX, advisories, reachability, attestations)
|
||||
- History/timeline of state changes and actions (append-only)
|
||||
- Copyable identifiers (finding ID, digests, correlation IDs)
|
||||
|
||||
## Offline / Air-Gap Notes
|
||||
|
||||
- When operating from Offline Kit snapshots, the Console should surface snapshot identity and staleness budgets.
|
||||
- Evidence bundle export is the primary bridge between online and offline review.
|
||||
|
||||
## References
|
||||
|
||||
- Console operator guide: `docs/UI_GUIDE.md`
|
||||
- Vulnerability Explorer guide: `docs/VULNERABILITY_EXPLORER_GUIDE.md`
|
||||
- Offline Kit: `docs/OFFLINE_KIT.md`
|
||||
@@ -0,0 +1,22 @@
|
||||
# Findings Ledger and Replay (Vulnerability Explorer)
|
||||
|
||||
The Findings Ledger is the append-only backbone for auditable triage. It records current finding state, history transitions, and operator actions in a way that supports deterministic replay and offline verification.
|
||||
|
||||
This document provides a conceptual overview; the authoritative schema and hashing rules are in the Findings Ledger module docs.
|
||||
|
||||
## What the Ledger Stores
|
||||
|
||||
- **Finding records:** enriched, policy-derived findings (with references to advisories/VEX/SBOM/reachability and explain traces).
|
||||
- **History:** append-only state transitions with actor identity, justification, and timestamps (UTC).
|
||||
- **Triage actions:** discrete operator actions (comment, assignment, mitigation note, ticket link) with immutable provenance.
|
||||
|
||||
## Replay and Verification
|
||||
|
||||
- Replay reconstructs derived state from append-only history/actions and compares deterministic digests.
|
||||
- Offline bundles include the ledger exports plus integrity metadata so auditors can verify without trusting a live service.
|
||||
|
||||
## References
|
||||
|
||||
- Findings Ledger schema: `docs/modules/findings-ledger/schema.md`
|
||||
- Merkle anchoring policy: `docs/modules/findings-ledger/merkle-anchor-policy.md`
|
||||
- Vulnerability Explorer dossier: `docs/modules/vuln-explorer/architecture.md`
|
||||
@@ -0,0 +1,247 @@
|
||||
# Signed VEX Override Workflow
|
||||
|
||||
This guide describes how to create and manage signed VEX override decisions using DSSE attestations for audit-grade provenance.
|
||||
|
||||
## Overview
|
||||
|
||||
VEX (Vulnerability Exploitability eXchange) decisions allow operators to mark vulnerabilities as not-affected, mitigated, or accepted-risk. When attestation signing is enabled, each override produces a DSSE envelope that:
|
||||
|
||||
1. Cryptographically binds the decision to the operator's identity
|
||||
2. Records the decision in an immutable attestation log
|
||||
3. Optionally anchors the attestation to Sigstore Rekor for transparency
|
||||
4. Enables downstream policy engines to require signed overrides
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Create Signed Override
|
||||
|
||||
```http
|
||||
POST /v1/vex-decisions
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer <token>
|
||||
|
||||
{
|
||||
"findingId": "find-abc123",
|
||||
"status": "NOT_AFFECTED",
|
||||
"justification": "CODE_NOT_REACHABLE",
|
||||
"justificationText": "Static analysis confirms code path is unreachable in production configuration",
|
||||
"scope": {
|
||||
"environments": ["production"],
|
||||
"projects": ["myapp"]
|
||||
},
|
||||
"validity": {
|
||||
"notBefore": "2026-01-15T00:00:00Z",
|
||||
"notAfter": "2026-07-15T00:00:00Z"
|
||||
},
|
||||
"attestationOptions": {
|
||||
"sign": true,
|
||||
"keyRef": "default-signing-key",
|
||||
"rekorUpload": true,
|
||||
"predicateType": "https://stella.ops/predicates/vex-override/v1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Response with Attestation Reference
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "vex-dec-xyz789",
|
||||
"findingId": "find-abc123",
|
||||
"status": "NOT_AFFECTED",
|
||||
"justification": "CODE_NOT_REACHABLE",
|
||||
"justificationText": "Static analysis confirms code path is unreachable in production configuration",
|
||||
"createdAt": "2026-01-15T10:30:00Z",
|
||||
"createdBy": "user@example.com",
|
||||
"signedOverride": {
|
||||
"envelopeDigest": "sha256:abc123def456...",
|
||||
"signatureAlgorithm": "ECDSA_P256_SHA256",
|
||||
"signedAt": "2026-01-15T10:30:01Z",
|
||||
"keyId": "default-signing-key",
|
||||
"rekorInfo": {
|
||||
"logIndex": 123456789,
|
||||
"entryId": "24296fb24b8ad77a...",
|
||||
"integratedTime": "2026-01-15T10:30:02Z",
|
||||
"logId": "c0d23d6ad406973f..."
|
||||
},
|
||||
"verificationStatus": "VERIFIED"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Update Signed Override
|
||||
|
||||
Updates create superseding records while preserving history:
|
||||
|
||||
```http
|
||||
PATCH /v1/vex-decisions/{id}
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer <token>
|
||||
|
||||
{
|
||||
"status": "AFFECTED_MITIGATED",
|
||||
"justification": "COMPENSATING_CONTROLS",
|
||||
"justificationText": "WAF rule deployed to block exploit vectors",
|
||||
"attestationOptions": {
|
||||
"sign": true,
|
||||
"supersedes": "vex-dec-xyz789"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### List Decisions with Attestation Filter
|
||||
|
||||
```http
|
||||
GET /v1/vex-decisions?signedOnly=true&rekorAnchored=true
|
||||
```
|
||||
|
||||
### Verify Attestation
|
||||
|
||||
```http
|
||||
POST /v1/vex-decisions/{id}/verify
|
||||
```
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{
|
||||
"verified": true,
|
||||
"signatureValid": true,
|
||||
"rekorEntryValid": true,
|
||||
"certificateChain": ["CN=signing-key,..."],
|
||||
"verifiedAt": "2026-01-15T10:35:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## CLI Usage
|
||||
|
||||
### Create Signed Override
|
||||
|
||||
```bash
|
||||
stella vex create \
|
||||
--finding find-abc123 \
|
||||
--status NOT_AFFECTED \
|
||||
--justification CODE_NOT_REACHABLE \
|
||||
--reason "Static analysis confirms unreachable" \
|
||||
--sign \
|
||||
--key default-signing-key \
|
||||
--rekor
|
||||
```
|
||||
|
||||
### View Override with Attestation
|
||||
|
||||
```bash
|
||||
stella vex show vex-dec-xyz789 --include-attestation
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
VEX Decision: vex-dec-xyz789
|
||||
Finding: find-abc123
|
||||
Status: NOT_AFFECTED
|
||||
Justification: CODE_NOT_REACHABLE
|
||||
Created: 2026-01-15T10:30:00Z
|
||||
Created By: user@example.com
|
||||
|
||||
Attestation:
|
||||
Envelope Digest: sha256:abc123def456...
|
||||
Algorithm: ECDSA_P256_SHA256
|
||||
Signed At: 2026-01-15T10:30:01Z
|
||||
Verification: VERIFIED
|
||||
|
||||
Rekor Entry:
|
||||
Log Index: 123456789
|
||||
Entry ID: 24296fb24b8ad77a...
|
||||
Integrated Time: 2026-01-15T10:30:02Z
|
||||
```
|
||||
|
||||
### Verify Override Attestation
|
||||
|
||||
```bash
|
||||
stella vex verify vex-dec-xyz789
|
||||
```
|
||||
|
||||
### Export Override Evidence
|
||||
|
||||
```bash
|
||||
stella vex export vex-dec-xyz789 \
|
||||
--format bundle \
|
||||
--output override-evidence.zip
|
||||
```
|
||||
|
||||
## Policy Engine Integration
|
||||
|
||||
Signed overrides can be required by policy rules:
|
||||
|
||||
```yaml
|
||||
# Policy requiring signed VEX overrides
|
||||
rules:
|
||||
- id: require-signed-vex
|
||||
condition: |
|
||||
vex.status in ["NOT_AFFECTED", "AFFECTED_MITIGATED"]
|
||||
and (vex.signedOverride == null or vex.signedOverride.verificationStatus != "VERIFIED")
|
||||
action: FAIL
|
||||
message: "VEX overrides must be signed and verified"
|
||||
```
|
||||
|
||||
## Attestation Predicate Schema
|
||||
|
||||
The VEX override predicate follows in-toto attestation format:
|
||||
|
||||
```json
|
||||
{
|
||||
"_type": "https://in-toto.io/Statement/v1",
|
||||
"subject": [
|
||||
{
|
||||
"name": "finding:find-abc123",
|
||||
"digest": { "sha256": "..." }
|
||||
}
|
||||
],
|
||||
"predicateType": "https://stella.ops/predicates/vex-override/v1",
|
||||
"predicate": {
|
||||
"decision": {
|
||||
"id": "vex-dec-xyz789",
|
||||
"status": "NOT_AFFECTED",
|
||||
"justification": "CODE_NOT_REACHABLE",
|
||||
"justificationText": "...",
|
||||
"scope": { "environments": ["production"] },
|
||||
"validity": { "notBefore": "...", "notAfter": "..." }
|
||||
},
|
||||
"finding": {
|
||||
"id": "find-abc123",
|
||||
"cve": "CVE-2026-1234",
|
||||
"package": "example-pkg",
|
||||
"version": "1.2.3"
|
||||
},
|
||||
"operator": {
|
||||
"identity": "user@example.com",
|
||||
"authorizedAt": "2026-01-15T10:30:00Z"
|
||||
},
|
||||
"supersedes": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Key Management**: Signing keys should be managed through Authority with appropriate access controls
|
||||
2. **Rekor Anchoring**: Enable Rekor upload for public transparency; disable for air-gapped deployments
|
||||
3. **Expiry**: Set appropriate validity windows; expired overrides surface warnings
|
||||
4. **Audit Trail**: All signed overrides are recorded in the findings ledger history
|
||||
|
||||
## Offline/Air-Gap Mode
|
||||
|
||||
For air-gapped deployments:
|
||||
|
||||
1. Rekor upload is disabled automatically
|
||||
2. Attestations are stored locally with envelope digests
|
||||
3. Verification uses local trust roots
|
||||
4. Export bundles include all attestation evidence for manual verification
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [VEX Consensus Guide](../../../VEX_CONSENSUS_GUIDE.md)
|
||||
- [Attestor Architecture](../../attestor/architecture.md)
|
||||
- [Findings Ledger](./findings-ledger.md)
|
||||
- [Policy Integration](../../policy/guides/vex-trust-model.md)
|
||||
24
docs-archived/modules/vuln-explorer/implementation_plan.md
Normal file
24
docs-archived/modules/vuln-explorer/implementation_plan.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Vuln Explorer Implementation Plan
|
||||
|
||||
## Purpose
|
||||
Provide a living plan for Vuln Explorer deliverables, dependencies, and evidence.
|
||||
|
||||
## Active work
|
||||
- Track current sprints under `docs/implplan/SPRINT_*.md` for this module.
|
||||
- Update this file when new scoped work is approved.
|
||||
|
||||
## Near-term deliverables
|
||||
- TBD (add when sprint is staffed).
|
||||
|
||||
## Dependencies
|
||||
- `docs/modules/vuln-explorer/architecture.md`
|
||||
- `docs/modules/vuln-explorer/README.md`
|
||||
- `docs/modules/platform/architecture-overview.md`
|
||||
|
||||
## Evidence of completion
|
||||
- Code changes under `src/VulnExplorer/**`.
|
||||
- Tests and fixtures under the module's `__Tests` / `__Libraries`.
|
||||
- Docs and runbooks under `docs/modules/vuln-explorer/**`.
|
||||
|
||||
## Notes
|
||||
- Keep deterministic and offline-first expectations aligned with module AGENTS.
|
||||
@@ -0,0 +1,188 @@
|
||||
# Vuln Explorer API · v1 (draft 2025-11-25)
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: StellaOps Vuln Explorer API
|
||||
version: "1.0.0-draft.2025-11-25"
|
||||
description: >
|
||||
Read-only vulnerability exploration surface. All responses are deterministic
|
||||
under identical inputs and include policy version + rationale identifiers.
|
||||
servers:
|
||||
- url: https://{host}
|
||||
variables:
|
||||
host:
|
||||
default: vuln-explorer.local
|
||||
tags:
|
||||
- name: Vulns
|
||||
paths:
|
||||
/vulns:
|
||||
get:
|
||||
summary: List vulnerabilities
|
||||
tags: [Vulns]
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/Tenant'
|
||||
- $ref: '#/components/parameters/PolicyVersion'
|
||||
- $ref: '#/components/parameters/PageSize'
|
||||
- $ref: '#/components/parameters/PageToken'
|
||||
- $ref: '#/components/parameters/Cve'
|
||||
- $ref: '#/components/parameters/Purl'
|
||||
- $ref: '#/components/parameters/Severity'
|
||||
- $ref: '#/components/parameters/Exploitability'
|
||||
- $ref: '#/components/parameters/FixAvailable'
|
||||
responses:
|
||||
'200':
|
||||
description: Paged vulnerabilities ordered by (score desc, id asc).
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/VulnListResponse'
|
||||
/vulns/{id}:
|
||||
get:
|
||||
summary: Get vulnerability by stable ID
|
||||
tags: [Vulns]
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/Tenant'
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: Stable vulnerability id (hash over source ids+purls).
|
||||
responses:
|
||||
'200':
|
||||
description: Vulnerability detail with evidence/provenance.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Vuln'
|
||||
'404':
|
||||
description: Not found for tenant/policy scope.
|
||||
|
||||
components:
|
||||
parameters:
|
||||
Tenant:
|
||||
name: x-stella-tenant
|
||||
in: header
|
||||
required: true
|
||||
schema: { type: string }
|
||||
description: Tenant identifier; required for all endpoints.
|
||||
PolicyVersion:
|
||||
name: policyVersion
|
||||
in: query
|
||||
schema: { type: string }
|
||||
description: Policy version/rationale to contextualise scores.
|
||||
PageSize:
|
||||
name: pageSize
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
minimum: 1
|
||||
maximum: 200
|
||||
default: 50
|
||||
description: Max items per page.
|
||||
PageToken:
|
||||
name: pageToken
|
||||
in: query
|
||||
schema: { type: string }
|
||||
description: Opaque token encoding last (score,id) tuple.
|
||||
Cve:
|
||||
name: cve
|
||||
in: query
|
||||
schema: { type: array, items: { type: string }, minItems: 1 }
|
||||
style: form
|
||||
explode: true
|
||||
description: Filter by CVE ids.
|
||||
Purl:
|
||||
name: purl
|
||||
in: query
|
||||
schema: { type: array, items: { type: string }, minItems: 1 }
|
||||
style: form
|
||||
explode: true
|
||||
description: Filter by PURL(s); matches affected packages.
|
||||
Severity:
|
||||
name: severity
|
||||
in: query
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum: [CRITICAL, HIGH, MEDIUM, LOW, NONE]
|
||||
style: form
|
||||
explode: true
|
||||
description: Filter by normalized severity band.
|
||||
Exploitability:
|
||||
name: exploitability
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
enum: [known, likely, unknown, none]
|
||||
description: Derived exploitability flag (from KEV + VEX + telemetry).
|
||||
FixAvailable:
|
||||
name: fixAvailable
|
||||
in: query
|
||||
schema: { type: boolean }
|
||||
description: Whether at least one fix is available.
|
||||
|
||||
schemas:
|
||||
VulnListResponse:
|
||||
type: object
|
||||
properties:
|
||||
items:
|
||||
type: array
|
||||
items: { $ref: '#/components/schemas/Vuln' }
|
||||
nextPageToken:
|
||||
type: string
|
||||
description: Opaque token encoding last (score,id) tuple.
|
||||
required: [items]
|
||||
Vuln:
|
||||
type: object
|
||||
properties:
|
||||
id: { type: string, description: Stable hash id }
|
||||
source:
|
||||
type: object
|
||||
properties:
|
||||
feed: { type: string, description: Original source/feed name }
|
||||
advisoryId: { type: string }
|
||||
cveIds:
|
||||
type: array
|
||||
items: { type: string }
|
||||
ghsaIds:
|
||||
type: array
|
||||
items: { type: string }
|
||||
purls:
|
||||
type: array
|
||||
items: { type: string }
|
||||
severity: { type: string, enum: [CRITICAL, HIGH, MEDIUM, LOW, NONE] }
|
||||
score: { type: number, format: double, minimum: 0, maximum: 10 }
|
||||
kev: { type: boolean }
|
||||
exploitability: { type: string, enum: [known, likely, unknown, none] }
|
||||
fixAvailable: { type: boolean }
|
||||
summary: { type: string }
|
||||
affectedPackages:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
purl: { type: string }
|
||||
versions: { type: array, items: { type: string } }
|
||||
firstSeen: { type: string, format: date-time }
|
||||
lastSeen: { type: string, format: date-time }
|
||||
advisoryRefs:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
url: { type: string, format: uri }
|
||||
title: { type: string }
|
||||
policyVersion: { type: string }
|
||||
rationaleId: { type: string }
|
||||
provenance:
|
||||
type: object
|
||||
properties:
|
||||
ledgerEntryId: { type: string }
|
||||
evidenceBundleId: { type: string }
|
||||
required:
|
||||
- id
|
||||
- severity
|
||||
- score
|
||||
- policyVersion
|
||||
- rationaleId
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"_note": "Placeholder Grafana dashboard stub for offline import. Populate with panel definitions when metrics endpoints are available; see runbooks/observability.md for expected panels.",
|
||||
"schemaVersion": 39,
|
||||
"title": "Vuln Explorer Observability (stub)",
|
||||
"panels": []
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
# Vuln Explorer observability runbook (demo snapshot · 2025-11-29)
|
||||
|
||||
## Dashboards (offline-friendly)
|
||||
- Grafana JSON: `docs/modules/vuln-explorer/runbooks/dashboards/vuln-explorer-observability.json` (import locally; no external data sources assumed).
|
||||
- Ops dashboards: `ops/devops/vuln/dashboards/vuln-explorer.json` (CI/staging) adds API latency p95, projection lag, error rate, query budget enforcement.
|
||||
|
||||
## Key metrics
|
||||
- `vuln_projection_lag_seconds{tenant}` – seconds between latest ledger event and projector head.
|
||||
- `vuln_findings_open_total{severity,tenant}` – count of open findings by severity.
|
||||
- `vuln_export_duration_seconds_bucket` – histogram for export job runtime.
|
||||
- `vuln_projection_backlog_total` – queued events awaiting projection.
|
||||
- `vuln_triage_actions_total{type}` – immutable triage actions (assign, comment, risk_accept, remediation_note).
|
||||
- `vuln_api_request_duration_seconds_bucket{route}` – API latency for `GET /v1/findings*` and `POST /v1/reports`.
|
||||
- `vuln_query_hashes_total{tenant,query_hash}` – hashed query shapes (no PII) to observe cache effectiveness.
|
||||
- `vuln_api_payload_bytes_bucket{direction}` – request/response size histograms to spot oversized payloads.
|
||||
|
||||
## Logs & traces
|
||||
- Correlate by `correlationId` and `findingId`. Structured fields: `tenant`, `advisoryKey`, `policyVersion`, `projectId`, `route`.
|
||||
- Query PII guardrail: request filters are hashed (SHA-256 with deployment salt); raw filters are not logged. Strings longer than 128 chars are truncated; known PII fields (`email`, `userId`) are dropped before logging.
|
||||
- Trace exemplar anchors: `traceparent` headers are copied into logs; exporters stay disabled by default for air-gap. Enable by setting `Telemetry:ExportEnabled=true` and pointing to on-prem Tempo/Jaeger.
|
||||
|
||||
## Health/diagnostics
|
||||
- `/health/liveness` and `/health/readiness` (HTTP 200 expected; readiness checks PostgreSQL + cache reachability).
|
||||
- `/status` returns build version, git commit, and enabled features; safe for anonymous fetch in sealed environments.
|
||||
- Ledger replay check: `GET /v1/findings?projectionMode=verify` emits `X-Vuln-Projection-Head` for quick consistency probes.
|
||||
|
||||
## Alert hints (wire to local Alertmanager or watchdog)
|
||||
- Projection lag > 120s for any tenant.
|
||||
- API p99 latency > 800ms for `GET /v1/findings` or `POST /v1/reports`.
|
||||
- Export failure rate > 2% over 10m window.
|
||||
- Accepted-risk approaching expiry within 7d (emit Notify event `vuln.accepted_risk.expiring`).
|
||||
|
||||
## Offline verification steps
|
||||
1) Import Grafana JSON locally and point to Prometheus scrape job `vuln-explorer`.
|
||||
2) Run `stella vuln export --format json --manifest out/manifest.json` and validate hashes using `jq -r '.files[].sha256'` against generated bundle.
|
||||
3) Use `curl -s "$BASEURL/status" | jq '{commit,version,features}'` to confirm expected build metadata matches the exported bundle manifest.
|
||||
|
||||
## Evidence locations
|
||||
- Sprint alignment: `docs/implplan/SPRINT_0334_0001_0001_docs_modules_vuln_explorer.md`.
|
||||
- API contract draft: `docs/modules/vuln-explorer/api.md` and OpenAPI at `docs/modules/vuln-explorer/openapi/vuln-explorer.v1.yaml`.
|
||||
- Schema references: `docs/modules/vuln-explorer/architecture.md` (ledger model, VEX decision schemas).
|
||||
Reference in New Issue
Block a user