8.0 KiB
VEX Consensus and Issuer Trust
This document consolidates the VEX concepts StellaOps relies on: ingesting upstream VEX without rewriting it, correlating evidence across sources, and producing a deterministic, explainable "effective" status for a component-vulnerability pair.
Scope
- VEX ingestion and provenance (what is stored and why)
- Correlation (linksets) versus consensus (effective status)
- Issuer trust and offline operation
This is not an API reference; module dossiers define concrete schemas and endpoints.
Vocabulary (Minimal)
- VEX statement: a claim about vulnerability status for a product/component (for example:
affected,fixed,not_affected,under_investigation). - Observation: an immutable record of a single upstream VEX document as received (including provenance and raw payload).
- Linkset: a deterministic correlation group that ties together statements that refer to the same
(vulnerabilityId, productKey)across providers. - Consensus decision (effective VEX): the platform's deterministic result after policy rules evaluate available VEX/advisory/reachability evidence.
Observation Model (Link, Not Merge)
StellaOps treats upstream VEX as append-only evidence.
An observation records:
- Provenance: tenant, provider/issuer identity, receive timestamps (UTC), signature status, and content hash.
- Raw payload: stored losslessly so auditors and operators can retrieve exactly what was ingested.
- Derived tuples: extracted
(vulnerabilityId, productKey, status, justification?, version hints, references)used for correlation and UI presentation.
An observation is never mutated. If upstream publishes a revision, StellaOps stores a new observation and records a supersedes relationship.
Linksets (Correlation Without Consensus)
Linksets exist to make multi-source evidence explainable without collapsing it:
- Group statements that likely refer to the same product-vulnerability pair.
- Preserve conflicts (status disagreements, justification divergence, version range clashes) as first-class facts.
- Provide stable IDs generated from canonical, sorted inputs (deterministic hashing).
Linksets do not invent consensus; they only align evidence so downstream layers (Policy/Console/Exports) can explain what is known and what disagrees.
Consensus (Effective Status)
The effective VEX status is computed by policy evaluation using:
- Correlated VEX evidence (observations + linksets)
- Advisory evidence (observations/linksets from Concelier)
- Optional reachability and other signals
Key properties:
- Deterministic: the same inputs yield the same output.
- Explainable: the decision includes an explanation trace and evidence references.
- Uncertainty-aware: when critical evidence is missing or conflicts are unresolved, the result can remain
under_investigationinstead of implying safety.
Aggregation-Only Guardrails (AOC)
To avoid hidden rewriting of upstream data, the platform enforces:
- Raw-first storage: upstream payloads are stored as received; normalized projections are derived but do not replace raw data.
- No merge of sources: each provider's statements remain independently addressable.
- Provenance is mandatory: missing provenance or unverifiable signatures are surfaced as ingestion failures or warnings (policy-driven).
- Idempotent writes: identical content hashes do not create duplicate observations.
- Deterministic outputs: stable ordering and canonical hashing for linksets and exports.
Issuer Directory and Trust
Issuer trust is a first-class input:
- Issuers are identified by stable provider IDs and, where applicable, cryptographic identity (certificate chain, key id, transparency proof).
- The issuer directory defines which issuers are trusted per tenant/environment and how they are weighted/accepted by policy.
- Offline sites carry required trust material (roots and allowlists) inside the Offline Kit so verification does not require network access.
Console Integration
The Console uses these concepts to keep VEX explainable:
- VEX views show provider provenance, signature/issuer status, and snapshot timestamps.
- Conflicts are displayed as conflicts (what disagrees and why), not silently resolved in the UI.
- The effective VEX status shown in triage views links back to underlying observations/linksets and the policy explanation.
See docs/UI_GUIDE.md for the operator workflow perspective.
Anchor-Aware Mode (v1.1)
Sprint: SPRINT_20260112_004_BE_policy_determinization_attested_rules
Anchor-aware mode enforces cryptographic attestation requirements on VEX proofs used for allow decisions.
VexProofGate Options
| Option | Type | Default | Strict Mode |
|---|---|---|---|
AnchorAwareMode |
bool | false |
true |
RequireVexAnchoring |
bool | false |
true |
RequireRekorVerification |
bool | false |
true |
RequireSignedStatements |
bool | false |
true |
RequireProofForFixed |
bool | false |
true |
MaxAllowedConflicts |
int | 5 |
0 |
MaxProofAgeHours |
int | 168 |
72 |
Strict Anchor-Aware Preset
For production environments requiring maximum security:
var options = VexProofGateOptions.StrictAnchorAware;
// Enables: RequireVexAnchoring, RequireRekorVerification,
// RequireSignedStatements, RequireProofForFixed
// Sets: MinimumConfidenceTier=high, MaxAllowedConflicts=0, MaxProofAgeHours=72
Metadata Keys
When passing VEX proof context through policy evaluation:
| Key | Type | Description |
|---|---|---|
vex_proof_anchored |
bool | Whether proof has DSSE anchoring |
vex_proof_envelope_digest |
string | DSSE envelope sha256 digest |
vex_proof_rekor_verified |
bool | Whether Rekor transparency verified |
vex_proof_rekor_log_index |
long | Rekor log index if verified |
Failure Reasons
| Reason | Description |
|---|---|
vex_not_anchored |
VEX proof requires DSSE anchoring but is not anchored |
rekor_verification_missing |
VEX proof requires Rekor verification but not verified |
VEX Change Events
Sprint: SPRINT_20260112_006_EXCITITOR_vex_change_events
Excititor emits deterministic events when VEX statements change, enabling policy reanalysis.
Event Types
| Event | Description | Policy Trigger |
|---|---|---|
vex.statement.added |
New statement ingested | Immediate reanalysis |
vex.statement.superseded |
Statement replaced | Immediate reanalysis |
vex.statement.conflict |
Status disagreement detected | Queue for review |
vex.status.changed |
Effective status changed | Immediate reanalysis |
Conflict Detection
Conflicts are detected when multiple providers report different statuses for the same vulnerability-product pair:
| Conflict Type | Description |
|---|---|
status_mismatch |
Different status values (e.g., affected vs not_affected) |
trust_tie |
Equal trust scores with different recommendations |
supersession_conflict |
Disagreement on which statement supersedes |
Event Ordering
Events follow deterministic ordering:
- Ordered by timestamp (ascending)
- Conflict events after related statement events
- Same-timestamp events sorted by provider ID
Integration with Policy
Subscribe to VEX events for automatic reanalysis:
subscriptions:
- event: vex.statement.*
action: reanalyze
filter:
trustScore: { $gte: 0.7 }
See Excititor Architecture for full event schemas.
Offline / Air-Gap Operation
- VEX observations/linksets are included in Offline Kit snapshots with content hashes and timestamps.
- Verification workflows (signatures, issuer trust) must work offline using bundled trust roots and manifests.
- The Console should surface snapshot identity and staleness budgets when operating offline.
Related Docs
docs/modules/excititor/architecture.mddocs/modules/vex-lens/architecture.mddocs/ARCHITECTURE_OVERVIEW.mddocs/OFFLINE_KIT.md