Complete batch 012 (golden set diff) and 013 (advisory chat), fix build errors
Sprints completed: - SPRINT_20260110_012_* (golden set diff layer - 10 sprints) - SPRINT_20260110_013_* (advisory chat - 4 sprints) Build fixes applied: - Fix namespace conflicts with Microsoft.Extensions.Options.Options.Create - Fix VexDecisionReachabilityIntegrationTests API drift (major rewrite) - Fix VexSchemaValidationTests FluentAssertions method name - Fix FixChainGateIntegrationTests ambiguous type references - Fix AdvisoryAI test files required properties and namespace aliases - Add stub types for CveMappingController (ICveSymbolMappingService) - Fix VerdictBuilderService static context issue Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
340
docs/modules/attestor/fix-chain-predicate.md
Normal file
340
docs/modules/attestor/fix-chain-predicate.md
Normal file
@@ -0,0 +1,340 @@
|
||||
# FixChain Attestation Predicate
|
||||
|
||||
> **Sprint:** SPRINT_20260110_012_005_ATTESTOR
|
||||
> **Predicate Type:** `https://stella-ops.org/predicates/fix-chain/v1`
|
||||
> **Last Updated:** 10-Jan-2026
|
||||
|
||||
## Overview
|
||||
|
||||
The FixChain predicate provides cryptographically verifiable proof that a patch eliminates a vulnerable code path. It bridges the gap between vulnerability disclosure and fix verification by encoding evidence from binary analysis into a DSSE-signed attestation.
|
||||
|
||||
## Why FixChain?
|
||||
|
||||
| Current State | With FixChain |
|
||||
|---------------|---------------|
|
||||
| Trust vendor claims | Verify with evidence chain |
|
||||
| No attestable fix evidence | DSSE-signed fix proofs |
|
||||
| Version-based assumptions | Binary signature comparison |
|
||||
| No air-gap verification | Offline-verifiable bundles |
|
||||
|
||||
## Predicate Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"$id": "https://stella-ops.org/schemas/predicates/fix-chain/v1",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"cveId", "component", "goldenSetRef", "vulnerableBinary",
|
||||
"patchedBinary", "sbomRef", "signatureDiff", "reachability",
|
||||
"verdict", "analyzer", "analyzedAt"
|
||||
],
|
||||
"properties": {
|
||||
"cveId": {
|
||||
"description": "CVE or GHSA identifier",
|
||||
"pattern": "^CVE-\\d{4}-\\d{4,}$|^GHSA-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}$"
|
||||
},
|
||||
"component": {
|
||||
"description": "Component being verified"
|
||||
},
|
||||
"goldenSetRef": {
|
||||
"description": "Content-addressed reference to golden set definition"
|
||||
},
|
||||
"vulnerableBinary": {
|
||||
"description": "Pre-patch binary identity (SHA-256, architecture)"
|
||||
},
|
||||
"patchedBinary": {
|
||||
"description": "Post-patch binary identity (SHA-256, architecture, PURL)"
|
||||
},
|
||||
"sbomRef": {
|
||||
"description": "Reference to SBOM containing the component"
|
||||
},
|
||||
"signatureDiff": {
|
||||
"description": "Summary of signature differences"
|
||||
},
|
||||
"reachability": {
|
||||
"description": "Reachability analysis outcome"
|
||||
},
|
||||
"verdict": {
|
||||
"description": "Final fix determination",
|
||||
"properties": {
|
||||
"status": { "enum": ["fixed", "partial", "not_fixed", "inconclusive"] },
|
||||
"confidence": { "type": "number", "minimum": 0, "maximum": 1 },
|
||||
"rationale": { "type": "array", "items": { "type": "string" } }
|
||||
}
|
||||
},
|
||||
"analyzer": {
|
||||
"description": "Analyzer metadata for reproducibility"
|
||||
},
|
||||
"analyzedAt": {
|
||||
"description": "ISO 8601 timestamp"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Evidence Chain
|
||||
|
||||
The FixChain attestation encodes evidence from multiple analysis stages:
|
||||
|
||||
```
|
||||
Golden Set Definition (CVE signature)
|
||||
|
|
||||
v
|
||||
+------------------+ +------------------+
|
||||
| Vulnerable Binary| --> | Patch Diff Engine|
|
||||
+------------------+ +------------------+
|
||||
| |
|
||||
v v
|
||||
+------------------+ +------------------+
|
||||
| Patched Binary | --> | Signature Diff |
|
||||
+------------------+ +------------------+
|
||||
|
|
||||
v
|
||||
+------------------+
|
||||
| Reachability |
|
||||
| Analysis |
|
||||
+------------------+
|
||||
|
|
||||
v
|
||||
+------------------+
|
||||
| FixChain |
|
||||
| Attestation |
|
||||
+------------------+
|
||||
```
|
||||
|
||||
## Verdict Calculation
|
||||
|
||||
The verdict is calculated based on multiple factors:
|
||||
|
||||
### Status Values
|
||||
|
||||
| Status | Description | Conditions |
|
||||
|--------|-------------|------------|
|
||||
| `fixed` | Vulnerability fully addressed | High confidence (>=80%), all paths eliminated |
|
||||
| `partial` | Vulnerability partially addressed | Medium confidence (50-80%), some paths remain |
|
||||
| `not_fixed` | Vulnerability still present | Diff shows no fix, paths unchanged |
|
||||
| `inconclusive` | Cannot determine | Low confidence, insufficient evidence |
|
||||
|
||||
### Confidence Scoring
|
||||
|
||||
```
|
||||
Confidence = Base + FunctionBonus + EdgeBonus + PathBonus
|
||||
|
||||
Base = Diff.Confidence (from analysis)
|
||||
|
||||
FunctionBonus:
|
||||
- +0.1 per vulnerable function removed
|
||||
- +0.05 per vulnerable function modified
|
||||
|
||||
EdgeBonus:
|
||||
- +0.05 per vulnerable edge eliminated
|
||||
|
||||
PathBonus:
|
||||
- +0.3 if all paths eliminated
|
||||
- +0.1 if paths reduced by >50%
|
||||
```
|
||||
|
||||
### Rationale Generation
|
||||
|
||||
The rationale array explains the verdict:
|
||||
|
||||
```json
|
||||
{
|
||||
"rationale": [
|
||||
"3 vulnerable function(s) removed",
|
||||
"5 vulnerable edge(s) eliminated",
|
||||
"All paths to vulnerable sink eliminated"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Example Attestation
|
||||
|
||||
```json
|
||||
{
|
||||
"_type": "https://in-toto.io/Statement/v1",
|
||||
"subject": [{
|
||||
"name": "pkg:deb/debian/openssl@3.1.0",
|
||||
"digest": {
|
||||
"sha256": "abc123..."
|
||||
}
|
||||
}],
|
||||
"predicateType": "https://stella-ops.org/predicates/fix-chain/v1",
|
||||
"predicate": {
|
||||
"cveId": "CVE-2024-0727",
|
||||
"component": "openssl",
|
||||
"goldenSetRef": {
|
||||
"digest": "sha256:def456..."
|
||||
},
|
||||
"vulnerableBinary": {
|
||||
"sha256": "111111...",
|
||||
"architecture": "x86_64"
|
||||
},
|
||||
"patchedBinary": {
|
||||
"sha256": "222222...",
|
||||
"architecture": "x86_64",
|
||||
"purl": "pkg:deb/debian/openssl@3.1.0"
|
||||
},
|
||||
"sbomRef": {
|
||||
"digest": "sha256:789abc..."
|
||||
},
|
||||
"signatureDiff": {
|
||||
"vulnerableFunctionsRemoved": 1,
|
||||
"vulnerableFunctionsModified": 2,
|
||||
"vulnerableEdgesEliminated": 5,
|
||||
"sanitizersInserted": 0,
|
||||
"details": ["Function X509_VERIFY_PARAM_set_flags rewritten"]
|
||||
},
|
||||
"reachability": {
|
||||
"prePathCount": 3,
|
||||
"postPathCount": 0,
|
||||
"eliminated": true,
|
||||
"reason": "All 3 path(s) to vulnerable sink eliminated"
|
||||
},
|
||||
"verdict": {
|
||||
"status": "fixed",
|
||||
"confidence": 0.95,
|
||||
"rationale": [
|
||||
"1 vulnerable function(s) removed",
|
||||
"5 vulnerable edge(s) eliminated",
|
||||
"All paths to vulnerable sink eliminated"
|
||||
]
|
||||
},
|
||||
"analyzer": {
|
||||
"name": "StellaOps.BinaryIndex",
|
||||
"version": "1.0.0",
|
||||
"sourceDigest": "sha256:analyzerxyz..."
|
||||
},
|
||||
"analyzedAt": "2026-01-10T12:00:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## CLI Usage
|
||||
|
||||
### Create FixChain Attestation
|
||||
|
||||
```bash
|
||||
stella attest fixchain \
|
||||
--sbom sbom.cdx.json \
|
||||
--diff diff-result.json \
|
||||
--golden golden-set.yaml \
|
||||
--out fixchain.dsse.json \
|
||||
--arch x86_64 \
|
||||
--purl "pkg:deb/debian/openssl@3.1.0"
|
||||
```
|
||||
|
||||
### Verify FixChain Attestation
|
||||
|
||||
```bash
|
||||
stella attest fixchain-verify \
|
||||
--attestation fixchain.dsse.json \
|
||||
--format summary
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
[OK] FixChain attestation is valid
|
||||
CVE: CVE-2024-0727
|
||||
Component: openssl
|
||||
Verdict: fixed (95%)
|
||||
Analyzed: 2026-01-10T12:00:00Z
|
||||
```
|
||||
|
||||
### JSON Output
|
||||
|
||||
```bash
|
||||
stella attest fixchain-verify \
|
||||
--attestation fixchain.dsse.json \
|
||||
--format json
|
||||
```
|
||||
|
||||
## API Integration
|
||||
|
||||
### Service Registration
|
||||
|
||||
```csharp
|
||||
services.AddFixChainAttestation(opts =>
|
||||
{
|
||||
opts.AnalyzerName = "MyAnalyzer";
|
||||
opts.AnalyzerVersion = "1.0.0";
|
||||
opts.FixedConfidenceThreshold = 0.80m;
|
||||
});
|
||||
```
|
||||
|
||||
### Creating Attestation
|
||||
|
||||
```csharp
|
||||
var request = new FixChainBuildRequest
|
||||
{
|
||||
CveId = "CVE-2024-0727",
|
||||
Component = "openssl",
|
||||
GoldenSetDigest = goldenSetDigest,
|
||||
SbomDigest = sbomDigest,
|
||||
VulnerableBinary = new BinaryIdentity { ... },
|
||||
PatchedBinary = new BinaryIdentity { ... },
|
||||
ComponentPurl = "pkg:deb/debian/openssl@3.1.0",
|
||||
DiffResult = diffResult
|
||||
};
|
||||
|
||||
var result = await attestationService.CreateAsync(request);
|
||||
// result.EnvelopeJson - DSSE envelope
|
||||
// result.ContentDigest - SHA-256 of statement
|
||||
// result.Predicate - Parsed predicate
|
||||
```
|
||||
|
||||
### Verifying Attestation
|
||||
|
||||
```csharp
|
||||
var result = await attestationService.VerifyAsync(envelopeJson);
|
||||
if (result.IsValid)
|
||||
{
|
||||
var verdict = result.Predicate!.Verdict;
|
||||
Console.WriteLine($"Status: {verdict.Status}");
|
||||
Console.WriteLine($"Confidence: {verdict.Confidence:P0}");
|
||||
}
|
||||
```
|
||||
|
||||
## Air-Gap Verification
|
||||
|
||||
FixChain attestations support offline verification:
|
||||
|
||||
1. **Bundle Export**: Export attestation with all referenced artifacts
|
||||
2. **Signature Verification**: Verify DSSE signature with bundled public key
|
||||
3. **Content Validation**: Validate predicate structure and content
|
||||
4. **Optional Rekor Proof**: Include offline Rekor inclusion proof
|
||||
|
||||
```bash
|
||||
# Export bundle for air-gap
|
||||
stella attest bundle export \
|
||||
--attestation fixchain.dsse.json \
|
||||
--include-artifacts \
|
||||
--out fixchain-bundle.tar.gz
|
||||
|
||||
# Verify in air-gap
|
||||
stella attest bundle verify \
|
||||
--bundle fixchain-bundle.tar.gz \
|
||||
--offline
|
||||
```
|
||||
|
||||
## Related Documents
|
||||
|
||||
- [Golden Set Schema](../binary-index/golden-set-schema.md)
|
||||
- [SBOM Extension Fields](../binary-index/sbom-extensions.md)
|
||||
- [Proof Chain Specification](./proof-chain-specification.md)
|
||||
- [DSSE Roundtrip Verification](./dsse-roundtrip-verification.md)
|
||||
|
||||
## Configuration
|
||||
|
||||
```yaml
|
||||
Attestor:
|
||||
Predicates:
|
||||
FixChain:
|
||||
Enabled: true
|
||||
AnalyzerName: "StellaOps.BinaryIndex"
|
||||
AnalyzerVersion: "1.0.0"
|
||||
FixedConfidenceThreshold: 0.80
|
||||
PartialConfidenceThreshold: 0.50
|
||||
PublishToRekor: true
|
||||
Archive: true
|
||||
```
|
||||
Reference in New Issue
Block a user