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>
9.8 KiB
9.8 KiB
Policy Engine FixChain Gates
Sprint: SPRINT_20260110_012_008_POLICY Last Updated: 10-Jan-2026
Overview
FixChain gates are policy predicates that control release promotion based on verified fix status. They integrate FixChain attestations from the binary-level fix verification system into policy decisions, blocking or warning on releases that contain critical vulnerabilities without verified fixes.
Why This Matters
| Current State | With FixChain Gates |
|---|---|
| Manual fix verification | Automated policy gates |
| Trust vendor fix claims | Require verification evidence |
| Inconsistent release criteria | Codified fix requirements |
| Post-deployment discovery | Pre-deployment blocking |
Configuration
YAML Policy Configuration
# stellaops.yaml
Policy:
Predicates:
FixChainGate:
Enabled: true
DefaultMinConfidence: 0.85
DefaultGracePeriodDays: 7
NotifyOnBlock: true
NotifyOnWarn: true
policies:
release-gates:
name: "Release Gate Policy"
version: "1.0.0"
description: "Gates for production release promotion"
gates:
# Critical vulnerabilities - strict requirements
- name: "critical-fix-required"
predicate: fixChainRequired
parameters:
severities: ["critical"]
minConfidence: 0.95
allowInconclusive: false
gracePeriodDays: 3
requireApprovedGoldenSet: true
action: block
message: "Critical vulnerabilities require verified fix with 95%+ confidence"
# High vulnerabilities - moderate requirements
- name: "high-fix-recommended"
predicate: fixChainRequired
parameters:
severities: ["high"]
minConfidence: 0.80
allowInconclusive: true
gracePeriodDays: 14
requireApprovedGoldenSet: true
action: warn
message: "High vulnerabilities should have verified fix"
# Exception for specific components
- name: "vendor-component-exception"
predicate: componentException
parameters:
components:
- "pkg:deb/debian/vendor-lib@*"
reason: "Vendor provides attestation separately"
action: allow
fallback: block
auditLog: true
Parameter Reference
| Parameter | Type | Default | Description |
|---|---|---|---|
severities |
string[] | ["critical", "high"] |
Severity levels requiring verification |
minConfidence |
decimal | 0.85 |
Minimum confidence for "fixed" verdict |
allowInconclusive |
bool | false |
Whether inconclusive verdicts pass |
gracePeriodDays |
int | 7 |
Days after CVE publication before gate applies |
requireApprovedGoldenSet |
bool | true |
Require golden set to be approved |
failureAction |
string | block |
Action on failure: block or warn |
Gate Outcomes
| Outcome | Passed | Description |
|---|---|---|
FixVerified |
Yes | Fix verified with sufficient confidence |
SeverityExempt |
Yes | Severity does not require verification |
GracePeriod |
Yes | Within grace period after CVE publication |
AttestationRequired |
No | No attestation found, severity requires it |
InsufficientConfidence |
No | Confidence below threshold |
InconclusiveNotAllowed |
No | Inconclusive verdict, policy doesn't allow |
StillVulnerable |
No | Verification shows vulnerability present |
GoldenSetNotApproved |
No | Golden set not reviewed/approved |
PartialFix |
Depends | Partial fix detected |
K4 Lattice Integration
+-----------------+
| ReleaseBlocked |
+--------+--------+
|
+--------------------+--------------------+
| |
v v
+---------------+ +---------------+
| FixRequired | | ManualReview |
| (Critical+ | | Required |
| Unverified) | | |
+-------+-------+ +-------+-------+
| |
+--------------------+--------------------+
|
v
+-----------------+
| ReleaseAllowed |
+-----------------+
Lattice Rules:
Critical AND NoFixChain -> ReleaseBlocked
Critical AND FixChain(>=0.95) -> ReleaseAllowed
Critical AND Inconclusive -> ManualReviewRequired
High AND NoFixChain -> ManualReviewRequired
High AND FixChain(>=0.80) -> ReleaseAllowed
Usage
Programmatic Evaluation
// Inject the predicate
var predicate = services.GetRequiredService<IFixChainGatePredicate>();
// Create context for a finding
var context = new FixChainGateContext
{
CveId = "CVE-2024-12345",
ComponentPurl = "pkg:npm/lodash@4.17.20",
Severity = "critical",
CvssScore = 9.8m,
BinarySha256 = binaryDigest,
CvePublishedAt = DateTimeOffset.Parse("2024-01-15")
};
// Configure parameters
var parameters = new FixChainGateParameters
{
Severities = ImmutableArray.Create("critical", "high"),
MinConfidence = 0.90m,
AllowInconclusive = false,
GracePeriodDays = 7,
RequireApprovedGoldenSet = true
};
// Evaluate
var result = await predicate.EvaluateAsync(context, parameters, ct);
if (!result.Passed)
{
Console.WriteLine($"Gate blocked: {result.Reason}");
foreach (var rec in result.Recommendations)
{
Console.WriteLine($" - {rec}");
}
foreach (var cmd in result.CliCommands)
{
Console.WriteLine($" $ {cmd}");
}
}
Batch Evaluation
var batchService = services.GetRequiredService<IFixChainGateBatchService>();
var contexts = findings.Select(f => new FixChainGateContext
{
CveId = f.CveId,
ComponentPurl = f.ComponentPurl,
Severity = f.Severity,
CvssScore = f.CvssScore
}).ToList();
var batchResult = await batchService.EvaluateBatchAsync(contexts, parameters, ct);
if (!batchResult.AllPassed)
{
Console.WriteLine($"Blocking issues: {batchResult.BlockingResults.Length}");
Console.WriteLine($"Warnings: {batchResult.WarningResults.Length}");
}
Policy Gate Registry Integration
// In Startup/Program.cs
services.AddFixChainGate(configuration);
// Register with policy gate registry
var registry = services.BuildServiceProvider()
.GetRequiredService<IPolicyGateRegistry>();
registry.RegisterFixChainGate();
CLI Usage
Check Gates for an Artifact
stella policy check-gates \
--artifact sha256:abc123... \
--policy release-gates \
--format table
Output:
Release Gate Evaluation: sha256:abc123...
Policy: release-gates
+----------------------------+---------+----------------------------------------+
| Gate | Status | Reason |
+----------------------------+---------+----------------------------------------+
| critical-fix-required | PASS | No critical vulnerabilities |
| high-fix-recommended | WARN | 2 findings without verified fix |
| vendor-component-exception | PASS | Exception applied |
+----------------------------+---------+----------------------------------------+
Warnings (2):
- CVE-2024-1234 on pkg:npm/lodash@4.17.20: No FixChain attestation
- CVE-2024-5678 on pkg:npm/axios@0.21.0: Inconclusive verdict
Recommendations:
- stella scanner golden init --cve CVE-2024-1234 --component lodash
- stella scanner golden init --cve CVE-2024-5678 --component axios
Overall: ALLOWED (with warnings)
JSON Output
stella policy check-gates \
--artifact sha256:abc123... \
--policy release-gates \
--format json
Metrics
The gate exposes OpenTelemetry metrics:
| Metric | Type | Description |
|---|---|---|
policy_fixchain_gate_evaluations_total |
Counter | Total evaluations |
policy_fixchain_gate_passes_total |
Counter | Gate passes |
policy_fixchain_gate_blocks_total |
Counter | Gate blocks |
policy_fixchain_gate_warnings_total |
Counter | Gate warnings |
policy_fixchain_gate_evaluation_duration_seconds |
Histogram | Evaluation duration |
policy_fixchain_gate_errors_total |
Counter | Evaluation errors |
Troubleshooting
Gate Blocking Unexpectedly
-
Check severity configuration: Ensure the severity matches configured severities
stella policy show --policy release-gates -
Verify attestation exists: Check if attestation is present
stella attestor query --cve CVE-2024-XXXX --predicate fixchain -
Check confidence level: Verify confidence meets threshold
stella scanner golden show --cve CVE-2024-XXXX --verbose -
Review golden set status: Check if golden set is approved
stella scanner golden status --cve CVE-2024-XXXX
Grace Period Issues
- Grace period starts from CVE publication date in the advisory
- If publication date is unknown, grace period doesn't apply
- Use
--grace-period-overridefor manual override
Inconclusive Verdicts
Inconclusive verdicts typically occur when:
- Binary is stripped and symbols unavailable
- Golden set incomplete or too generic
- Compiler optimizations changed code structure
Resolution:
- Obtain debug symbols
- Enhance golden set with more specific targets
- Consider policy exception with justification