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>
341 lines
8.8 KiB
Markdown
341 lines
8.8 KiB
Markdown
# 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
|
|
```
|