audit work, fixed StellaOps.sln warnings/errors, fixed tests, sprints work, new advisories

This commit is contained in:
master
2026-01-07 18:49:59 +02:00
parent 04ec098046
commit 608a7f85c0
866 changed files with 56323 additions and 6231 deletions

View File

@@ -0,0 +1,176 @@
# Determinization Gate API Reference
> **Audience:** Backend integrators, policy operators, and security engineers working with CVE observations.
> **Sprint:** 20260106_001_003_POLICY_determinization_gates
This document describes the Determinization Gate API and the `GuardedPass` verdict status for uncertain CVE observations.
---
## 1. Overview
The Determinization Gate evaluates CVE observations against uncertainty thresholds and produces verdicts based on available evidence (EPSS, VEX, reachability, runtime, backport signals). It introduces `GuardedPass` status for observations that don't have enough evidence for a confident determination but don't exceed risk thresholds.
### Key Components
| Component | Purpose |
|-----------|---------|
| `DeterminizationGate` | Policy gate that evaluates uncertainty and produces verdicts |
| `DeterminizationPolicy` | Rule set for allow/quarantine/escalate decisions |
| `SignalUpdateHandler` | Handles signal updates and triggers re-evaluation |
| `DeterminizationGateMetrics` | OpenTelemetry metrics for observability |
---
## 2. PolicyVerdictStatus
Policy evaluations return a `PolicyVerdictStatus` indicating the outcome:
| Status | Code | Description | Monitoring Required |
|--------|------|-------------|---------------------|
| `Pass` | 0 | Finding meets policy requirements. No action needed. | No |
| `Blocked` | 1 | Finding fails policy checks; must be remediated. | No |
| `Ignored` | 2 | Finding deliberately ignored via policy exception. | No |
| `Warned` | 3 | Finding passes but with warnings. | No |
| `Deferred` | 4 | Decision deferred; needs additional evidence. | No |
| `Escalated` | 5 | Decision escalated for human review. | No |
| `RequiresVex` | 6 | VEX statement required to make decision. | No |
| `GuardedPass` | 7 | Finding allowed with runtime monitoring guardrails. | **Yes** |
---
## 3. GuardedPass Status
`GuardedPass` is a specialized status for CVE observations with uncertain evidence. It enables "allow with guardrails" semantics.
### 3.1 When Issued
- Observation has insufficient evidence for full determination (high entropy)
- Trust score below thresholds but above blocking level
- Non-production environments with moderate uncertainty
- Reachability status is unknown but not confirmed reachable
### 3.2 GuardRails Object
When `GuardedPass` is returned, the verdict includes a `guardRails` object:
```json
{
"status": "GuardedPass",
"reason": "Uncertain observation allowed with guardrails in staging",
"matchedRule": "GuardedAllowNonProd",
"guardRails": {
"enableRuntimeMonitoring": true,
"reviewInterval": "7.00:00:00",
"epssEscalationThreshold": 0.4,
"escalatingReachabilityStates": ["Reachable", "ObservedReachable"],
"maxGuardedDuration": "30.00:00:00",
"policyRationale": "Auto-allowed: entropy=0.45, trust=0.38, env=staging"
},
"suggestedObservationState": "PendingDeterminization",
"uncertaintyScore": {
"entropy": 0.45,
"completeness": 0.55,
"tier": "Medium",
"missingSignals": ["runtime", "backport"]
}
}
```
### 3.3 Consumer Responsibilities
When receiving `GuardedPass`:
1. **Enable Runtime Monitoring:** Start observing the component for vulnerable code execution
2. **Schedule Review:** Set up periodic review at `reviewInterval`
3. **EPSS Escalation:** Auto-escalate if EPSS score exceeds `epssEscalationThreshold`
4. **Reachability Escalation:** Auto-escalate if reachability transitions to escalating states
5. **Duration Limit:** Convert to `Blocked` if guard duration exceeds `maxGuardedDuration`
---
## 4. Determinization Rules
The gate evaluates rules in priority order:
| Priority | Rule | Condition | Result |
|----------|------|-----------|--------|
| 10 | RuntimeEscalation | Runtime evidence shows vulnerable code loaded | Escalated |
| 20 | EpssQuarantine | EPSS score exceeds threshold | Blocked |
| 25 | ReachabilityQuarantine | Code proven reachable | Blocked |
| 30 | ProductionEntropyBlock | High entropy in production | Blocked |
| 40 | StaleEvidenceDefer | Evidence is stale | Deferred |
| 50 | GuardedAllowNonProd | Uncertain in non-prod | GuardedPass |
| 60 | UnreachableAllow | Unreachable with high confidence | Pass |
| 65 | VexNotAffectedAllow | VEX not_affected from trusted issuer | Pass |
| 70 | SufficientEvidenceAllow | Low entropy, high trust | Pass |
| 80 | GuardedAllowModerateUncertainty | Moderate uncertainty, reasonable trust | GuardedPass |
| 100 | DefaultDefer | No rule matched | Deferred |
---
## 5. Environment Thresholds
Thresholds vary by deployment environment:
| Environment | MinConfidence | MaxEntropy | EPSS Threshold | Require Reachability |
|-------------|---------------|------------|----------------|---------------------|
| Production | 0.75 | 0.3 | 0.3 | Yes |
| Staging | 0.60 | 0.5 | 0.4 | Yes |
| Development | 0.40 | 0.7 | 0.6 | No |
---
## 6. Signal Update Events
The Determinization Gate subscribes to signal updates for automatic re-evaluation:
| Event Type | Description |
|------------|-------------|
| `epss.updated` | EPSS score changed |
| `vex.updated` | VEX statement added/modified |
| `reachability.updated` | Reachability analysis completed |
| `runtime.updated` | Runtime observation recorded |
| `backport.updated` | Backport detection result |
| `observation.state_changed` | Observation state transition |
---
## 7. Metrics
OpenTelemetry metrics for monitoring:
| Metric | Type | Description |
|--------|------|-------------|
| `stellaops_policy_determinization_evaluations_total` | Counter | Total evaluations by status/environment/rule |
| `stellaops_policy_determinization_rule_matches_total` | Counter | Rule matches by rule name/status/environment |
| `stellaops_policy_observation_state_transitions_total` | Counter | State transitions by from/to state/trigger |
| `stellaops_policy_determinization_entropy` | Histogram | Distribution of entropy scores |
| `stellaops_policy_determinization_trust_score` | Histogram | Distribution of trust scores |
| `stellaops_policy_determinization_evaluation_duration_ms` | Histogram | Evaluation latency |
---
## 8. Service Registration
Add determinization services via dependency injection:
```csharp
// Register all determinization services
services.AddDeterminizationEngine();
// Or as part of full Policy Engine registration
services.AddPolicyEngine(); // Includes determinization
```
---
## 9. Related Documentation
- [Determinization Library](./determinization-architecture.md) - Core determinization models
- [Policy Engine Architecture](./architecture.md) - Overall policy engine design
- [Signal Snapshot Models](../../api/signals/reachability-contract.md) - Signal data structures
---
*Last updated: 2026-01-07 (Sprint 20260106_001_003)*

View File

@@ -34,7 +34,7 @@
#### Activation configuration wiring
- **Helm ConfigMap.** `deploy/helm/stellaops/values*.yaml` now include a `policy-engine-activation` ConfigMap. The chart automatically injects it via `envFrom` into both the Policy Engine and Policy Gateway pods, so overriding the ConfigMap data updates the services with no manifest edits.
- **Helm ConfigMap.** `devops/helm/stellaops/values*.yaml` now include a `policy-engine-activation` ConfigMap. The chart automatically injects it via `envFrom` into both the Policy Engine and Policy Gateway pods, so overriding the ConfigMap data updates the services with no manifest edits.
- **Type safety.** Quote ConfigMap values (e.g., `"true"`, `"false"`) because Kubernetes ConfigMaps carry string data. This mirrors the defaults checked into the repo and keeps `helm template` deterministic.
- **File-based overrides (optional).** The Policy Engine host already probes `/config/policy-engine/activation.yaml`, `../etc/policy-engine.activation.yaml`, and ambient `policy-engine.activation.yaml` files beside the binary. Mounting the ConfigMap as a file at `/config/policy-engine/activation.yaml` works immediately if/when we add a volume.
- **Offline/Compose.** Compose/offline bundles can continue exporting `STELLAOPS_POLICY_ENGINE__ACTIVATION__*` variables directly; the ConfigMap wiring simply mirrors those keys for Kubernetes clusters.

View File

@@ -0,0 +1,369 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://stellaops.dev/schemas/stellaops.suppression.v1.schema.json",
"title": "StellaOps Suppression Witness v1",
"description": "A DSSE-signable suppression witness documenting why a vulnerability is not exploitable",
"type": "object",
"required": [
"witness_schema",
"witness_id",
"artifact",
"vuln",
"suppression_type",
"evidence",
"confidence",
"observed_at"
],
"properties": {
"witness_schema": {
"type": "string",
"const": "stellaops.suppression.v1",
"description": "Schema version identifier"
},
"witness_id": {
"type": "string",
"pattern": "^sup:sha256:[a-f0-9]{64}$",
"description": "Content-addressed witness ID (e.g., 'sup:sha256:...')"
},
"artifact": {
"$ref": "#/definitions/WitnessArtifact",
"description": "The artifact (SBOM, component) this witness relates to"
},
"vuln": {
"$ref": "#/definitions/WitnessVuln",
"description": "The vulnerability this witness concerns"
},
"suppression_type": {
"type": "string",
"enum": [
"Unreachable",
"LinkerGarbageCollected",
"FeatureFlagDisabled",
"PatchedSymbol",
"GateBlocked",
"CompileTimeExcluded",
"VexNotAffected",
"FunctionAbsent",
"VersionNotAffected",
"PlatformNotAffected"
],
"description": "The type of suppression (unreachable, patched, gate-blocked, etc.)"
},
"evidence": {
"$ref": "#/definitions/SuppressionEvidence",
"description": "Evidence supporting the suppression claim"
},
"confidence": {
"type": "number",
"minimum": 0.0,
"maximum": 1.0,
"description": "Confidence level in this suppression [0.0, 1.0]"
},
"expires_at": {
"type": "string",
"format": "date-time",
"description": "Optional expiration date for time-bounded suppressions (UTC ISO-8601)"
},
"observed_at": {
"type": "string",
"format": "date-time",
"description": "When this witness was generated (UTC ISO-8601)"
},
"justification": {
"type": "string",
"description": "Optional justification narrative"
}
},
"additionalProperties": false,
"definitions": {
"WitnessArtifact": {
"type": "object",
"required": ["sbom_digest", "component_purl"],
"properties": {
"sbom_digest": {
"type": "string",
"pattern": "^sha256:[a-f0-9]{64}$",
"description": "SHA-256 digest of the SBOM"
},
"component_purl": {
"type": "string",
"pattern": "^pkg:",
"description": "Package URL of the vulnerable component"
}
},
"additionalProperties": false
},
"WitnessVuln": {
"type": "object",
"required": ["id", "source", "affected_range"],
"properties": {
"id": {
"type": "string",
"description": "Vulnerability identifier (e.g., 'CVE-2024-12345')"
},
"source": {
"type": "string",
"description": "Vulnerability source (e.g., 'NVD', 'OSV', 'GHSA')"
},
"affected_range": {
"type": "string",
"description": "Affected version range expression"
}
},
"additionalProperties": false
},
"SuppressionEvidence": {
"type": "object",
"required": ["witness_evidence"],
"properties": {
"witness_evidence": {
"$ref": "#/definitions/WitnessEvidence"
},
"unreachability": {
"$ref": "#/definitions/UnreachabilityEvidence"
},
"patched_symbol": {
"$ref": "#/definitions/PatchedSymbolEvidence"
},
"function_absent": {
"$ref": "#/definitions/FunctionAbsentEvidence"
},
"gate_blocked": {
"$ref": "#/definitions/GateBlockedEvidence"
},
"feature_flag": {
"$ref": "#/definitions/FeatureFlagEvidence"
},
"vex_statement": {
"$ref": "#/definitions/VexStatementEvidence"
},
"version_range": {
"$ref": "#/definitions/VersionRangeEvidence"
},
"linker_gc": {
"$ref": "#/definitions/LinkerGcEvidence"
}
},
"additionalProperties": false
},
"WitnessEvidence": {
"type": "object",
"required": ["callgraph_digest"],
"properties": {
"callgraph_digest": {
"type": "string",
"description": "BLAKE3 digest of the call graph used"
},
"surface_digest": {
"type": "string",
"description": "SHA-256 digest of the attack surface manifest"
},
"analysis_config_digest": {
"type": "string",
"description": "SHA-256 digest of the analysis configuration"
},
"build_id": {
"type": "string",
"description": "Build identifier for the analyzed artifact"
}
},
"additionalProperties": false
},
"UnreachabilityEvidence": {
"type": "object",
"required": ["analyzed_entrypoints", "unreachable_symbol", "analysis_method", "graph_digest"],
"properties": {
"analyzed_entrypoints": {
"type": "integer",
"minimum": 0,
"description": "Number of entrypoints analyzed"
},
"unreachable_symbol": {
"type": "string",
"description": "Vulnerable symbol that was confirmed unreachable"
},
"analysis_method": {
"type": "string",
"description": "Analysis method (static, dynamic, hybrid)"
},
"graph_digest": {
"type": "string",
"description": "Graph digest for reproducibility"
}
},
"additionalProperties": false
},
"FunctionAbsentEvidence": {
"type": "object",
"required": ["function_name", "binary_digest", "verification_method"],
"properties": {
"function_name": {
"type": "string",
"description": "Vulnerable function name"
},
"binary_digest": {
"type": "string",
"description": "Binary digest where function was checked"
},
"verification_method": {
"type": "string",
"description": "Verification method (symbol table scan, disassembly, etc.)"
}
},
"additionalProperties": false
},
"GateBlockedEvidence": {
"type": "object",
"required": ["detected_gates", "gate_coverage_percent", "effectiveness"],
"properties": {
"detected_gates": {
"type": "array",
"items": {
"$ref": "#/definitions/DetectedGate"
},
"description": "Detected gates along all paths to vulnerable code"
},
"gate_coverage_percent": {
"type": "integer",
"minimum": 0,
"maximum": 100,
"description": "Minimum gate coverage percentage [0, 100]"
},
"effectiveness": {
"type": "string",
"description": "Gate effectiveness assessment"
}
},
"additionalProperties": false
},
"DetectedGate": {
"type": "object",
"required": ["type", "guard_symbol", "confidence"],
"properties": {
"type": {
"type": "string",
"description": "Gate type (authRequired, inputValidation, rateLimited, etc.)"
},
"guard_symbol": {
"type": "string",
"description": "Symbol that implements the gate"
},
"confidence": {
"type": "number",
"minimum": 0.0,
"maximum": 1.0,
"description": "Confidence level (0.0 - 1.0)"
},
"detail": {
"type": "string",
"description": "Human-readable detail about the gate"
}
},
"additionalProperties": false
},
"PatchedSymbolEvidence": {
"type": "object",
"required": ["vulnerable_symbol", "patched_symbol", "symbol_diff"],
"properties": {
"vulnerable_symbol": {
"type": "string",
"description": "Vulnerable symbol identifier"
},
"patched_symbol": {
"type": "string",
"description": "Patched symbol identifier"
},
"symbol_diff": {
"type": "string",
"description": "Symbol diff showing the patch"
},
"patch_ref": {
"type": "string",
"description": "Patch commit or release reference"
}
},
"additionalProperties": false
},
"VexStatementEvidence": {
"type": "object",
"required": ["vex_id", "vex_author", "vex_status", "vex_digest"],
"properties": {
"vex_id": {
"type": "string",
"description": "VEX statement identifier"
},
"vex_author": {
"type": "string",
"description": "VEX statement author/authority"
},
"vex_status": {
"type": "string",
"enum": ["not_affected", "fixed"],
"description": "VEX statement status"
},
"vex_digest": {
"type": "string",
"description": "Content digest of the VEX document"
}
},
"additionalProperties": false
},
"FeatureFlagEvidence": {
"type": "object",
"required": ["flag_name", "flag_state", "verification_source"],
"properties": {
"flag_name": {
"type": "string",
"description": "Feature flag name/key"
},
"flag_state": {
"type": "string",
"description": "Feature flag state (off, disabled)"
},
"verification_source": {
"type": "string",
"description": "Source of flag verification (config file, runtime)"
}
},
"additionalProperties": false
},
"VersionRangeEvidence": {
"type": "object",
"required": ["actual_version", "affected_range", "comparison_method"],
"properties": {
"actual_version": {
"type": "string",
"description": "Actual version of the component"
},
"affected_range": {
"type": "string",
"description": "Affected version range from advisory"
},
"comparison_method": {
"type": "string",
"description": "Version comparison method used"
}
},
"additionalProperties": false
},
"LinkerGcEvidence": {
"type": "object",
"required": ["removed_symbol", "linker_method", "verification_digest"],
"properties": {
"removed_symbol": {
"type": "string",
"description": "Symbol removed by linker GC"
},
"linker_method": {
"type": "string",
"description": "Linker garbage collection method"
},
"verification_digest": {
"type": "string",
"description": "Digest of final binary for verification"
}
},
"additionalProperties": false
}
}
}