152 lines
4.7 KiB
Markdown
152 lines
4.7 KiB
Markdown
# VEX Override Predicate Specification
|
|
|
|
## Overview
|
|
|
|
The VEX Override predicate provides a cryptographically signed record of operator decisions to override or annotate vulnerability assessments. This enables auditable, tamper-evident records of security triage decisions within the StellaOps vulnerability management workflow.
|
|
|
|
## Predicate Type URI
|
|
|
|
```
|
|
https://stellaops.dev/attestations/vex-override/v1
|
|
```
|
|
|
|
## Use Cases
|
|
|
|
1. **not_affected**: Document that a vulnerability does not affect the artifact in its deployed configuration
|
|
2. **mitigated**: Record compensating controls that address the vulnerability
|
|
3. **accepted**: Acknowledge an accepted risk with proper authorization
|
|
4. **under_investigation**: Mark a vulnerability as being actively assessed
|
|
|
|
## Schema
|
|
|
|
### Required Fields
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `artifactDigest` | string | Artifact digest this override applies to (e.g., `sha256:abc123...`) |
|
|
| `vulnerabilityId` | string | CVE or vulnerability identifier being overridden |
|
|
| `decision` | string/enum | One of: `not_affected`, `mitigated`, `accepted`, `under_investigation` |
|
|
| `justification` | string | Human-readable explanation for the decision |
|
|
| `decisionTime` | ISO 8601 | UTC timestamp when the decision was made |
|
|
| `operatorId` | string | Identifier of the operator who made the decision |
|
|
|
|
### Optional Fields
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `expiresAt` | ISO 8601 | When this override should be re-evaluated |
|
|
| `evidenceRefs` | array | References to supporting documentation |
|
|
| `tool` | object | Information about the tool creating the predicate |
|
|
| `ruleDigest` | string | Digest of the policy rule that triggered evaluation |
|
|
| `traceHash` | string | Hash of reachability analysis at decision time |
|
|
| `metadata` | object | Additional key-value metadata |
|
|
|
|
### Evidence Reference Schema
|
|
|
|
```json
|
|
{
|
|
"type": "document|ticket|scan_report|attestation",
|
|
"uri": "https://...",
|
|
"digest": "sha256:...",
|
|
"description": "Optional description"
|
|
}
|
|
```
|
|
|
|
### Tool Schema
|
|
|
|
```json
|
|
{
|
|
"name": "StellaOps",
|
|
"version": "1.0.0",
|
|
"vendor": "StellaOps Inc"
|
|
}
|
|
```
|
|
|
|
## Sample Payload
|
|
|
|
```json
|
|
{
|
|
"artifactDigest": "sha256:a1b2c3d4e5f6...",
|
|
"decision": "not_affected",
|
|
"decisionTime": "2026-01-14T10:00:00Z",
|
|
"evidenceRefs": [
|
|
{
|
|
"description": "Security review document",
|
|
"digest": "sha256:def456...",
|
|
"type": "document",
|
|
"uri": "https://docs.example.com/security-review/123"
|
|
}
|
|
],
|
|
"justification": "Component is compiled without the vulnerable code path due to build configuration",
|
|
"operatorId": "security-team@example.com",
|
|
"predicateType": "https://stellaops.dev/attestations/vex-override/v1",
|
|
"ruleDigest": "sha256:rule789...",
|
|
"tool": {
|
|
"name": "StellaOps",
|
|
"vendor": "StellaOps Inc",
|
|
"version": "1.0.0"
|
|
},
|
|
"traceHash": "sha256:trace012...",
|
|
"vulnerabilityId": "CVE-2024-12345"
|
|
}
|
|
```
|
|
|
|
## Canonicalization Rules
|
|
|
|
VEX override predicates MUST be serialized using RFC 8785 JSON Canonicalization Scheme (JCS) before signing:
|
|
|
|
1. **Key ordering**: All object keys are sorted lexicographically (Unicode code point order)
|
|
2. **Number format**: No exponent notation, no leading zeros, no trailing zeros after decimal
|
|
3. **String encoding**: Default JSON escaping (no relaxed escaping)
|
|
4. **Whitespace**: Minified JSON (no whitespace between tokens)
|
|
5. **Property naming**: Original snake_case field names preserved (no camelCase conversion)
|
|
|
|
### Serializer Configuration
|
|
|
|
```csharp
|
|
// DO NOT use CamelCase naming policy
|
|
// DO NOT use UnsafeRelaxedJsonEscaping
|
|
// Use JsonCanonicalizer.Canonicalize() before signing
|
|
|
|
var canonicalJson = JsonCanonicalizer.Canonicalize(payloadJson);
|
|
```
|
|
|
|
## DSSE Envelope Structure
|
|
|
|
```json
|
|
{
|
|
"payloadType": "https://stellaops.dev/attestations/vex-override/v1",
|
|
"payload": "<base64-encoded-canonical-predicate>",
|
|
"signatures": [
|
|
{
|
|
"keyid": "key-identifier",
|
|
"sig": "<base64-signature>"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## Verification
|
|
|
|
1. Decode the base64 payload
|
|
2. Verify the signature using DSSE PAE (Pre-Authentication Encoding)
|
|
3. Parse and validate the predicate schema
|
|
4. Check expiration if `expiresAt` is present
|
|
5. Optionally verify transparency log inclusion (Rekor anchoring)
|
|
|
|
## Offline Verification
|
|
|
|
The predicate supports offline verification when:
|
|
- The signing certificate chain is bundled
|
|
- Transparency log proofs are embedded
|
|
- No network access is required for validation
|
|
|
|
See [Rekor Verification Design](./rekor-verification-design.md) for transparency log integration details.
|
|
|
|
## Related Documents
|
|
|
|
- [Attestor Architecture](./architecture.md)
|
|
- [DSSE Roundtrip Verification](./dsse-roundtrip-verification.md)
|
|
- [Transparency Logging](./transparency.md)
|
|
- [VEX Consensus Guide](../../VEX_CONSENSUS_GUIDE.md)
|