355 lines
11 KiB
Markdown
355 lines
11 KiB
Markdown
# VEX Proof Object Schema Reference
|
|
|
|
Version: 1.0 (stellaops.vex-proof.v1)
|
|
Last Updated: 2026-01-03
|
|
|
|
## Overview
|
|
|
|
VEX Proof Objects provide a cryptographically verifiable audit trail of how VEX consensus verdicts are computed. Every VEX resolution in StellaOps produces a proof object that documents the inputs, merge process, and decision rationale.
|
|
|
|
## JSON Schema
|
|
|
|
```json
|
|
{
|
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
"title": "VEX Proof Object",
|
|
"type": "object",
|
|
"required": ["schema", "proofId", "computedAt", "verdict", "inputs", "mergeTrace", "confidence"],
|
|
"properties": {
|
|
"schema": {
|
|
"type": "string",
|
|
"const": "stellaops.vex-proof.v1"
|
|
},
|
|
"proofId": {
|
|
"type": "string",
|
|
"description": "Unique identifier for this proof"
|
|
},
|
|
"computedAt": {
|
|
"type": "string",
|
|
"format": "date-time",
|
|
"description": "ISO 8601 timestamp of proof computation"
|
|
},
|
|
"digest": {
|
|
"type": "object",
|
|
"description": "Content-addressed hash of the proof"
|
|
},
|
|
"verdict": {
|
|
"$ref": "#/definitions/verdict"
|
|
},
|
|
"inputs": {
|
|
"$ref": "#/definitions/inputs"
|
|
},
|
|
"mergeTrace": {
|
|
"$ref": "#/definitions/mergeTrace"
|
|
},
|
|
"propagation": {
|
|
"$ref": "#/definitions/propagation"
|
|
},
|
|
"conditions": {
|
|
"$ref": "#/definitions/conditions"
|
|
},
|
|
"confidence": {
|
|
"$ref": "#/definitions/confidence"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Object Definitions
|
|
|
|
### Verdict
|
|
|
|
The final consensus result.
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `vulnerabilityId` | string | Yes | CVE or vulnerability identifier |
|
|
| `productKey` | string | Yes | Product identifier (typically a PURL) |
|
|
| `status` | enum | Yes | VEX status: `affected`, `not_affected`, `fixed`, `under_investigation` |
|
|
| `justification` | enum | No | Justification code if status is `not_affected` |
|
|
| `confidence` | number | Yes | Confidence score [0.0, 1.0] |
|
|
|
|
```json
|
|
{
|
|
"vulnerabilityId": "CVE-2023-12345",
|
|
"productKey": "pkg:npm/lodash@4.17.21",
|
|
"status": "not_affected",
|
|
"justification": "vulnerable_code_not_in_execute_path",
|
|
"confidence": 0.78
|
|
}
|
|
```
|
|
|
|
### Inputs
|
|
|
|
All VEX statements considered in the consensus.
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `qualifiedCount` | integer | Yes | Number of statements meeting weight threshold |
|
|
| `disqualifiedCount` | integer | Yes | Number of statements filtered out |
|
|
| `statements` | array | Yes | Array of input statements |
|
|
| `disqualified` | array | No | Array of disqualified statements with reasons |
|
|
|
|
#### Statement Object
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `id` | string | Yes | Statement identifier |
|
|
| `source` | string | Yes | Source document identifier |
|
|
| `issuer` | object | Yes | Issuer information |
|
|
| `status` | enum | Yes | VEX status from this statement |
|
|
| `justification` | enum | No | Justification if not_affected |
|
|
| `weight` | object | Yes | Weight calculation details |
|
|
| `timestamp` | datetime | Yes | Statement timestamp |
|
|
| `signatureVerified` | boolean | Yes | Whether signature was verified |
|
|
|
|
#### Issuer Object
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `id` | string | Yes | Issuer identifier |
|
|
| `category` | enum | Yes | `vendor`, `distributor`, `community`, `internal`, `aggregator` |
|
|
| `trustTier` | enum | Yes | `authoritative`, `trusted`, `untrusted`, `unknown` |
|
|
|
|
#### Weight Object
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `composite` | number | Yes | Final composite weight [0.0, 1.0] |
|
|
| `factors` | object | Yes | Individual weight factors |
|
|
|
|
Weight factors:
|
|
- `issuer`: Issuer trust weight
|
|
- `signature`: Signature verification weight
|
|
- `freshness`: Statement age weight
|
|
- `format`: Source format weight (OpenVEX vs CSAF vs CycloneDX)
|
|
- `specificity`: Status specificity weight
|
|
|
|
### MergeTrace
|
|
|
|
Step-by-step documentation of the merge algorithm.
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `mode` | enum | Yes | Consensus mode used |
|
|
| `latticeOrdering` | array | No | Status lattice order (for Lattice mode) |
|
|
| `steps` | array | Yes | Array of merge steps |
|
|
| `conflicts` | array | No | Array of detected conflicts |
|
|
|
|
#### Consensus Modes
|
|
|
|
- `highest_weight`: Select statement with highest trust weight
|
|
- `weighted_vote`: Weighted voting across all statements
|
|
- `lattice`: Lattice-based conservative consensus
|
|
- `authoritative_first`: Prefer vendor/authoritative sources
|
|
|
|
#### Merge Step
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `stepNumber` | integer | Yes | Sequential step number |
|
|
| `statementId` | string | Yes | Statement being processed |
|
|
| `inputStatus` | enum | Yes | Status from this statement |
|
|
| `inputWeight` | number | Yes | Weight of this statement |
|
|
| `action` | enum | Yes | `initialize`, `merge`, `skip` |
|
|
| `conflictDetected` | boolean | Yes | Whether conflict was detected |
|
|
| `resolution` | string | No | How conflict was resolved |
|
|
| `positionAfter` | enum | Yes | Current consensus position after step |
|
|
|
|
#### Conflict
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `statement1Id` | string | Yes | First conflicting statement |
|
|
| `statement2Id` | string | Yes | Second conflicting statement |
|
|
| `status1` | enum | Yes | Status of first statement |
|
|
| `status2` | enum | Yes | Status of second statement |
|
|
| `severity` | enum | Yes | `critical`, `high`, `medium`, `low` |
|
|
| `resolution` | string | Yes | Resolution method |
|
|
| `winnerId` | string | No | Winning statement ID |
|
|
|
|
### Propagation
|
|
|
|
Dependency propagation analysis (optional).
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `applied` | boolean | Yes | Whether propagation was applied |
|
|
| `rules` | array | Yes | Propagation rules evaluated |
|
|
| `paths` | array | No | Analyzed dependency paths |
|
|
| `inheritedStatus` | enum | No | Status inherited via propagation |
|
|
| `overrideApplied` | boolean | No | Whether propagation overrode consensus |
|
|
|
|
#### Propagation Rules
|
|
|
|
- `direct_dependency_affected`: Affected status propagates to direct dependents
|
|
- `transitive_dependency`: Transitive propagation through dependency tree
|
|
- `dependency_fixed`: Fixed status doesn't propagate transitively
|
|
- `dependency_not_affected`: NotAffected can propagate under conditions
|
|
|
|
### Conditions
|
|
|
|
Condition evaluation results (optional).
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `results` | array | Yes | Condition evaluation results |
|
|
| `unevaluated` | array | No | Conditions that couldn't be evaluated |
|
|
| `coverage` | number | Yes | Percentage of conditions evaluated |
|
|
|
|
#### Condition Result
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `conditionId` | string | Yes | Condition identifier |
|
|
| `expression` | string | Yes | Condition expression |
|
|
| `result` | enum | Yes | `true`, `false`, `unknown` |
|
|
| `contextValue` | string | No | Evaluated context value |
|
|
|
|
#### Condition Types
|
|
|
|
- `platform`: OS/architecture (e.g., `linux/amd64`)
|
|
- `distro`: Distribution (e.g., `rhel:9`)
|
|
- `feature`: Feature flag condition
|
|
- `build_flag`: Compile-time flag
|
|
- `environment`: Environment variable
|
|
|
|
### Confidence
|
|
|
|
Confidence score breakdown.
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `score` | number | Yes | Overall confidence [0.0, 1.0] |
|
|
| `tier` | enum | Yes | `high`, `medium`, `low` |
|
|
| `components` | object | Yes | Score components |
|
|
| `improvements` | array | No | Suggestions for improving confidence |
|
|
|
|
Score component contributions:
|
|
- `weightSpread`: Statement weight distribution
|
|
- `freshnessBonus`: Bonus for recent statements
|
|
- `signatureBonus`: Bonus for signed statements
|
|
- `conflictPenalty`: Penalty for conflicts
|
|
- `conditionCoverage`: Condition evaluation coverage
|
|
|
|
## Digest Computation
|
|
|
|
The proof digest is computed using RFC 8785 canonical JSON serialization:
|
|
|
|
1. Serialize proof object to canonical JSON (sorted keys, minimal escaping)
|
|
2. Compute SHA-256 hash of canonical JSON bytes
|
|
3. Encode as hexadecimal
|
|
|
|
```json
|
|
{
|
|
"digest": {
|
|
"algorithm": "sha256",
|
|
"value": "a1b2c3d4..."
|
|
}
|
|
}
|
|
```
|
|
|
|
## Example Proof Object
|
|
|
|
```json
|
|
{
|
|
"schema": "stellaops.vex-proof.v1",
|
|
"proofId": "proof-2026-01-02T10:30:00Z-abc123",
|
|
"computedAt": "2026-01-02T10:30:00Z",
|
|
"digest": {
|
|
"algorithm": "sha256",
|
|
"value": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
|
},
|
|
"verdict": {
|
|
"vulnerabilityId": "CVE-2023-12345",
|
|
"productKey": "pkg:npm/lodash@4.17.21",
|
|
"status": "not_affected",
|
|
"justification": "vulnerable_code_not_in_execute_path",
|
|
"confidence": 0.78
|
|
},
|
|
"inputs": {
|
|
"qualifiedCount": 2,
|
|
"disqualifiedCount": 0,
|
|
"statements": [
|
|
{
|
|
"id": "stmt-001",
|
|
"source": "openvex",
|
|
"issuer": {
|
|
"id": "lodash-maintainers",
|
|
"category": "vendor",
|
|
"trustTier": "authoritative"
|
|
},
|
|
"status": "not_affected",
|
|
"justification": "vulnerable_code_not_in_execute_path",
|
|
"weight": {
|
|
"composite": 0.85,
|
|
"factors": {
|
|
"issuer": 0.90,
|
|
"signature": 1.00,
|
|
"freshness": 0.95,
|
|
"format": 1.00,
|
|
"specificity": 0.70
|
|
}
|
|
},
|
|
"timestamp": "2023-06-15T10:30:00Z",
|
|
"signatureVerified": true
|
|
}
|
|
]
|
|
},
|
|
"mergeTrace": {
|
|
"mode": "lattice",
|
|
"latticeOrdering": ["affected", "under_investigation", "fixed", "not_affected"],
|
|
"steps": [
|
|
{
|
|
"stepNumber": 1,
|
|
"statementId": "stmt-001",
|
|
"inputStatus": "not_affected",
|
|
"inputWeight": 0.85,
|
|
"action": "initialize",
|
|
"conflictDetected": false,
|
|
"positionAfter": "not_affected"
|
|
}
|
|
],
|
|
"conflicts": []
|
|
},
|
|
"confidence": {
|
|
"score": 0.78,
|
|
"tier": "medium",
|
|
"components": {
|
|
"weightSpread": 0.80,
|
|
"freshnessBonus": 0.05,
|
|
"signatureBonus": 0.05,
|
|
"conflictPenalty": 0.00,
|
|
"conditionCoverage": 0.00
|
|
},
|
|
"improvements": [
|
|
"Add statements from additional authoritative sources",
|
|
"Evaluate platform-specific conditions"
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
## Policy Integration
|
|
|
|
VEX proofs integrate with the policy gate system via `VexProofGate`:
|
|
|
|
| Setting | Type | Default | Description |
|
|
|---------|------|---------|-------------|
|
|
| `Enabled` | bool | true | Enable/disable gate |
|
|
| `MinimumConfidenceTier` | string | medium | Required confidence tier |
|
|
| `RequireProofForNotAffected` | bool | true | Require proof for NotAffected |
|
|
| `RequireProofForFixed` | bool | false | Require proof for Fixed |
|
|
| `MaxAllowedConflicts` | int | 5 | Maximum allowed conflicts |
|
|
| `MaxProofAgeHours` | int | 168 | Maximum proof age (hours) |
|
|
| `RequireSignedStatements` | bool | false | Require all statements signed |
|
|
| `MinimumInputStatements` | int | 1 | Minimum input statement count |
|
|
|
|
## Related Documentation
|
|
|
|
- [VEX Consensus Guide](../16_VEX_CONSENSUS_GUIDE.md)
|
|
- [Trust Weight Configuration](../trust-weights.md)
|
|
- [Policy Gates Reference](../policy-gates.md)
|
|
- [OpenVEX Specification](https://github.com/openvex/spec)
|
|
- [CycloneDX VEX](https://cyclonedx.org/use-cases/vulnerability-exploitability/)
|