Files
git.stella-ops.org/docs/contracts/triage-suppress-v1.md
2026-02-19 22:07:11 +02:00

178 lines
6.5 KiB
Markdown

# Contract: Triage Auto-Suppress Predicate (v1)
## Status
- Status: DRAFT (2026-02-19)
- Owner: Signals Guild, VexLens Guild
- Sprint: SPRINT_20260219_012
## Purpose
Define the `stella.ops/triageSuppress@v1` predicate type used when a runtime micro-witness DSSE confirms that a vulnerability's `canonical_id` matches a VEX `not_affected` consensus, enabling automatic triage suppression with full auditability.
## Predicate Type URI
```
stella.ops/triageSuppress@v1
```
## When This Predicate Is Emitted
The TriageSuppressJoinService emits this predicate when ALL of the following conditions are met:
1. A micro-witness DSSE exists for `(canonical_id, cve_id)` with observation type `RuntimeUnobserved` or a path witness with lattice state `ConfirmedUnreachable` or `StaticallyUnreachable`
2. VexLens consensus for `(canonical_id, cve_id)` has status `not_affected`
3. VexLens consensus confidence score >= configured threshold (default: 0.75 for production)
## Suppression Rules Truth Table
| VEX Status | Reachability State | Action | Requires Human Review |
|---|---|---|---|
| `not_affected` | `ConfirmedUnreachable` (CU) | **AUTO-SUPPRESS** | No |
| `not_affected` | `StaticallyUnreachable` (SU) | **AUTO-SUPPRESS** | No |
| `not_affected` | `RuntimeUnobserved` (RU) | **AUTO-SUPPRESS** | No |
| `not_affected` | `Unknown` (U) | LOG ONLY | Yes |
| `not_affected` | `StaticallyReachable` (SR) | LOG ONLY | Yes |
| `not_affected` | `RuntimeObserved` (RO) | LOG ONLY, FLAG CONFLICT | Yes |
| `not_affected` | `ConfirmedReachable` (CR) | LOG ONLY, FLAG CONFLICT | Yes |
| `not_affected` | `Contested` (X) | LOG ONLY, FLAG CONFLICT | Yes |
| `affected` | any | NEVER SUPPRESS | Yes |
| `under_investigation` | any | NEVER SUPPRESS | Yes |
| `fixed` | any | NEVER SUPPRESS (separate workflow) | No |
## Predicate Schema
```json
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Triage Suppress Predicate v1",
"type": "object",
"required": ["cve_id", "suppress_reason", "vex_consensus", "witness_evidence", "reachability_state", "timestamp"],
"properties": {
"cve_id": {
"type": "string",
"description": "CVE identifier (e.g., CVE-2025-0001)",
"pattern": "^CVE-\\d{4}-\\d{4,}$"
},
"suppress_reason": {
"type": "string",
"enum": ["vex_not_affected_with_unreachability_confirmation"],
"description": "Machine-readable reason for suppression"
},
"vex_consensus": {
"type": "object",
"required": ["status", "confidence_score", "consensus_digest", "computed_at"],
"properties": {
"status": { "type": "string", "enum": ["not_affected"] },
"justification": { "type": "string" },
"confidence_score": { "type": "number", "minimum": 0, "maximum": 1 },
"consensus_digest": { "type": "string", "description": "SHA-256 of the VexLens consensus record" },
"source_count": { "type": "integer", "description": "Number of VEX sources contributing" },
"computed_at": { "type": "string", "format": "date-time" }
}
},
"witness_evidence": {
"type": "object",
"required": ["witness_id", "dsse_digest", "observation_type"],
"properties": {
"witness_id": { "type": "string", "description": "Witness ID (wit:sha256:...)" },
"dsse_digest": { "type": "string", "description": "SHA-256 of the witness DSSE envelope" },
"observation_type": { "type": "string", "enum": ["RuntimeUnobserved", "ConfirmedUnreachable", "StaticallyUnreachable"] },
"predicate_type": { "type": "string", "description": "URI of the witness predicate type" }
}
},
"reachability_state": {
"type": "string",
"enum": ["ConfirmedUnreachable", "StaticallyUnreachable", "RuntimeUnobserved"],
"description": "Lattice state from the 8-state reachability model"
},
"timestamp": {
"type": "string",
"format": "date-time",
"description": "UTC timestamp of suppression evaluation"
},
"deterministic_replay_inputs": {
"type": "object",
"description": "Inputs sufficient to replay this suppression decision",
"properties": {
"canonical_id": { "type": "string" },
"vex_consensus_digest": { "type": "string" },
"witness_id": { "type": "string" }
}
}
}
}
```
## DSSE Envelope Shape
```json
{
"_type": "https://in-toto.io/Statement/v1",
"subject": [
{
"name": "artifact",
"digest": {
"sha256": "<canonical_id_hex>"
}
}
],
"predicateType": "stella.ops/triageSuppress@v1",
"predicate": {
"cve_id": "CVE-2025-0001",
"suppress_reason": "vex_not_affected_with_unreachability_confirmation",
"vex_consensus": {
"status": "not_affected",
"justification": "vulnerable_code_not_in_execute_path",
"confidence_score": 0.92,
"consensus_digest": "sha256:abc123...",
"source_count": 3,
"computed_at": "2026-02-19T12:00:00Z"
},
"witness_evidence": {
"witness_id": "wit:sha256:def456...",
"dsse_digest": "sha256:789abc...",
"observation_type": "ConfirmedUnreachable",
"predicate_type": "https://stella.ops/predicates/path-witness/v1"
},
"reachability_state": "ConfirmedUnreachable",
"timestamp": "2026-02-19T12:05:00Z",
"deterministic_replay_inputs": {
"canonical_id": "sha256:...",
"vex_consensus_digest": "sha256:abc123...",
"witness_id": "wit:sha256:def456..."
}
}
}
```
## Idempotency
Given the same `(canonical_id, cve_id, vex_consensus_digest, witness_id)`, the service MUST produce byte-identical DSSE output. This is enforced by:
- Deterministic JSON serialization (RFC 8785 / JCS)
- Deterministic timestamp: use the latest of `vex_consensus.computed_at` and witness `observed_at`
- No random or time-varying fields
## Policy Opt-In
Auto-suppress is disabled by default. Operators must enable it via policy configuration:
```json
{
"triage_suppress": {
"enabled": true,
"minimum_vex_confidence": 0.75,
"allowed_reachability_states": ["ConfirmedUnreachable", "StaticallyUnreachable", "RuntimeUnobserved"],
"require_rekor_anchor": true
}
}
```
## Audit Trail
Every suppression evaluation (whether it results in suppression or not) is logged:
- Suppressed: triageSuppress@v1 DSSE → Signer → Attestor → Rekor
- Not suppressed: audit log entry with reason (e.g., "vex_status=affected", "reachability=Contested")
## References
- SPRINT_20260219_012
- Reachability Lattice: `docs/modules/reach-graph/guides/lattice.md`
- VexLens Consensus: `docs/modules/vex-lens/architecture.md`
- Witness Contract: `docs/contracts/witness-v1.md`