Refactor SurfaceCacheValidator to simplify oldest entry calculation
Add global using for Xunit in test project Enhance ImportValidatorTests with async validation and quarantine checks Implement FileSystemQuarantineServiceTests for quarantine functionality Add integration tests for ImportValidator to check monotonicity Create BundleVersionTests to validate version parsing and comparison logic Implement VersionMonotonicityCheckerTests for monotonicity checks and activation logic
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
# Sprint 0336.0001.0001 - Product Advisories (14-Dec-2025) Thematic References
|
||||
|
||||
## Topic & Scope
|
||||
- Distill raw advisories under `docs/product-advisories/archived/14-Dec-2025/` into 12 themed technical references under `docs/product-advisories/`.
|
||||
- Ensure each themed reference is complete, non-repetitive, and developer-usable (schemas/checklists; no chatty prose).
|
||||
- Evidence: updated themed docs with coverage mapping and placeholder/schema cleanups.
|
||||
- **Working directory:** `docs/product-advisories`.
|
||||
|
||||
## Dependencies & Concurrency
|
||||
- None (documentation-only). Safe to execute in parallel with code sprints.
|
||||
|
||||
## Documentation Prerequisites
|
||||
- `docs/README.md`
|
||||
- `docs/07_HIGH_LEVEL_ARCHITECTURE.md`
|
||||
- `docs/AGENTS.md`
|
||||
- Source set: `docs/product-advisories/archived/14-Dec-2025/`
|
||||
|
||||
## Delivery Tracker
|
||||
| # | Task ID | Status | Key dependency / next step | Owners | Task Definition |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 1 | ADV-0336-001 | DONE (2025-12-14) | Source corpus exists; start with coverage diff. | Docs Guild (`docs/product-advisories`) | Inventory 51 raw advisories and 12 themed docs; map sources to themes and identify gaps. |
|
||||
| 2 | ADV-0336-002 | DONE (2025-12-14) | After #1. | Docs Guild (`docs/product-advisories`) | Fill missing technical content in themed docs (GraphRevisionID, reachability query/caching, bench harness rules, Postgres decision checklists, provenance-rich binaries). |
|
||||
| 3 | ADV-0336-003 | DONE (2025-12-14) | After #2. | Docs Guild (`docs/product-advisories`) | Normalize schema placeholders and remove unusable artifacts in technical references. |
|
||||
| 4 | ADV-0336-004 | DONE (2025-12-14) | After #3. | Docs Guild (`docs/product-advisories`) | Validate coverage: every raw advisory referenced by at least one themed doc; no external/chatty prose remains. |
|
||||
|
||||
## Wave Coordination
|
||||
- N/A (single wave).
|
||||
|
||||
## Wave Detail Snapshots
|
||||
- 2025-12-14: Consolidation completed; see Execution Log and themed doc list under `docs/product-advisories/`.
|
||||
|
||||
## Interlocks
|
||||
- None.
|
||||
|
||||
## Upcoming Checkpoints
|
||||
- None scheduled; re-open if new advisories land under `docs/product-advisories/**`.
|
||||
|
||||
## Action Tracker
|
||||
| Action | Owner | Due | Status |
|
||||
| --- | --- | --- | --- |
|
||||
| — | — | — | — |
|
||||
|
||||
## Decisions & Risks
|
||||
| Item | Type | Owner(s) | Due | Notes |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Unicode rendering in Windows PowerShell | Risk | Docs Guild | — | The themed references are UTF-8; use `Get-Content -Encoding UTF8` if viewing them in Windows PowerShell 5.1 to avoid mojibake. |
|
||||
|
||||
## Execution Log
|
||||
| Date (UTC) | Update | Owner |
|
||||
| --- | --- | --- |
|
||||
| 2025-12-14 | Sprint created and completed: consolidated 14-Dec-2025 advisory set into themed technical references; added missing content (graphRevisionId/receipts, reachability methods, bench/packaging rules, Postgres checklists, provenance-rich binaries) and cleaned schema placeholders. Evidence: `docs/product-advisories/*.md`. | Docs Guild |
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
# Sprint 0337.0001.0001 - CVSS Advisory Technical Enhancement
|
||||
|
||||
## Topic & Scope
|
||||
- Enhance `docs/product-advisories/14-Dec-2025 - CVSS and Competitive Analysis Technical Reference.md` with:
|
||||
1. CVSS v4.0 MacroVector scoring system explanation
|
||||
2. Threat Metrics multipliers documentation
|
||||
3. Receipt system overview
|
||||
4. KEV integration formula
|
||||
- **Working directory:** `docs/product-advisories`
|
||||
|
||||
## Dependencies & Concurrency
|
||||
- None (documentation-only). Safe to execute in parallel with code sprints.
|
||||
- Reference implementation: `src/Policy/StellaOps.Policy.Scoring/Engine/CvssV4Engine.cs`
|
||||
|
||||
## Documentation Prerequisites
|
||||
- `docs/README.md`
|
||||
- `docs/07_HIGH_LEVEL_ARCHITECTURE.md`
|
||||
- `docs/product-advisories/14-Dec-2025 - CVSS and Competitive Analysis Technical Reference.md`
|
||||
- Source implementation: `src/Policy/StellaOps.Policy.Scoring/`
|
||||
|
||||
## Delivery Tracker
|
||||
|
||||
| # | Task ID | Status | Key dependency / next step | Owners | Task Definition |
|
||||
|---|---------|--------|---------------------------|--------|-----------------|
|
||||
| 1 | CVSS-0337-001 | DONE (2025-12-14) | Source code review complete | Docs Guild | Add Section 1.4: CVSS v4.0 MacroVector Scoring System with EQ1-EQ6 equivalence class explanation |
|
||||
| 2 | CVSS-0337-002 | DONE (2025-12-14) | After #1 | Docs Guild | Add Section 1.5: Threat Metrics and Exploit Maturity multipliers table |
|
||||
| 3 | CVSS-0337-003 | DONE (2025-12-14) | After #2 | Docs Guild | Add Section 1.6: Environmental Score Modifiers documentation |
|
||||
| 4 | CVSS-0337-004 | DONE (2025-12-14) | After #3 | Docs Guild | Add Section 1.7: Supplemental Metrics (non-scoring) overview |
|
||||
| 5 | CVSS-0337-005 | DONE (2025-12-14) | After #4 | Docs Guild | Add Section 2.4: Deterministic Receipt System for CVSS decisions |
|
||||
| 6 | CVSS-0337-006 | DONE (2025-12-14) | After #5 | Docs Guild | Add Section 6.6: CVSS + KEV Risk Signal Combination formula |
|
||||
| 7 | CVSS-0337-007 | DONE (2025-12-14) | After #6 | Docs Guild | Validate all technical content against implementation code |
|
||||
|
||||
## Wave Coordination
|
||||
- Single wave; all documentation tasks sequential.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
**Task CVSS-0337-001 (MacroVector Scoring)**
|
||||
- [ ] Explains 6-digit MacroVector format (EQ1-EQ6)
|
||||
- [ ] Documents what each EQ represents
|
||||
- [ ] Shows scoring flow: metrics -> MacroVector -> lookup -> score
|
||||
- [ ] Includes code reference to `CvssV4Engine.cs:262-359`
|
||||
|
||||
**Task CVSS-0337-002 (Threat Metrics)**
|
||||
- [ ] Documents all Exploit Maturity values (A/P/U/X)
|
||||
- [ ] Shows multiplier values: Attacked=1.0, PoC=0.94, Unreported=0.91
|
||||
- [ ] Explains CVSS-BT score computation
|
||||
- [ ] Includes code reference to `CvssV4Engine.cs:365-375`
|
||||
|
||||
**Task CVSS-0337-003 (Environmental Modifiers)**
|
||||
- [ ] Documents Security Requirements (CR/IR/AR) multipliers
|
||||
- [ ] Shows modifier effects on base metrics
|
||||
- [ ] Explains CVSS-BE score computation
|
||||
|
||||
**Task CVSS-0337-004 (Supplemental Metrics)**
|
||||
- [ ] Lists all 6 supplemental metrics
|
||||
- [ ] Explains each is non-scoring but informative
|
||||
- [ ] Notes this is new in v4.0
|
||||
|
||||
**Task CVSS-0337-005 (Receipt System)**
|
||||
- [ ] Documents receipt schema fields
|
||||
- [ ] Explains InputHash computation
|
||||
- [ ] Shows how receipts enable determinism
|
||||
|
||||
**Task CVSS-0337-006 (KEV Integration)**
|
||||
- [ ] Documents formula: `clamp01((cvss/10) + 0.2*kev)`
|
||||
- [ ] Explains KEV bonus rationale
|
||||
- [ ] Code reference to `CvssKevProvider.cs`
|
||||
|
||||
## Interlocks
|
||||
- None.
|
||||
|
||||
## Decisions & Risks
|
||||
|
||||
| Item | Type | Owner(s) | Due | Notes |
|
||||
|------|------|----------|-----|-------|
|
||||
| Confirm EQ formula accuracy | Risk | Docs Guild | Before merge | Verify EQ1-EQ6 logic matches FIRST spec |
|
||||
|
||||
## Action Tracker
|
||||
|
||||
| Action | Due (UTC) | Owner(s) | Notes |
|
||||
|--------|-----------|----------|-------|
|
||||
| Review FIRST CVSS v4.0 spec | Before merge | Docs Guild | Ensure EQ formulas are accurate |
|
||||
|
||||
## Execution Log
|
||||
|
||||
| Date (UTC) | Update | Owner |
|
||||
|------------|--------|-------|
|
||||
| 2025-12-14 | Sprint created; tasks defined from advisory gap analysis. | Docs Guild |
|
||||
| 2025-12-14 | All tasks completed. Added sections 1.4-1.7 (CVSS v4.0 MacroVector, Threat Metrics, Environmental Modifiers, Supplemental Metrics), section 2.4 (Deterministic Receipt System), and section 6.6 (CVSS + KEV Risk Formula) to advisory. Content validated against `CvssV4Engine.cs` implementation. | Docs Guild |
|
||||
|
||||
## Next Checkpoints
|
||||
|
||||
| Date (UTC) | Session | Goal | Owner(s) |
|
||||
|------------|---------|------|----------|
|
||||
| TBD | Documentation review | Validate technical accuracy | Docs Guild |
|
||||
@@ -0,0 +1,550 @@
|
||||
# Sprint 0338.0001.0001 - CVSS/EPSS Development Work
|
||||
|
||||
## Topic & Scope
|
||||
Complete missing CVSS and EPSS infrastructure identified in advisory gap analysis:
|
||||
1. Complete MacroVector lookup table (486 entries)
|
||||
2. EPSS integration service
|
||||
3. CVSS v2/v3 receipt support
|
||||
- **Working directory:** `src/Policy/` and `src/RiskEngine/`
|
||||
|
||||
## Dependencies & Concurrency
|
||||
- Depends on: CVSS v4.0 Engine (EXISTS: `CvssV4Engine.cs`)
|
||||
- Depends on: Receipt infrastructure (EXISTS: `ReceiptBuilder.cs`)
|
||||
- Can run in parallel with documentation sprints
|
||||
|
||||
## Documentation Prerequisites
|
||||
- `docs/product-advisories/14-Dec-2025 - CVSS and Competitive Analysis Technical Reference.md`
|
||||
- FIRST CVSS v4.0 Specification (external)
|
||||
- FIRST EPSS Documentation (external)
|
||||
- `src/Policy/StellaOps.Policy.Scoring/Engine/CvssV4Engine.cs`
|
||||
- `src/Policy/StellaOps.Policy.Scoring/Engine/MacroVectorLookup.cs`
|
||||
|
||||
## Delivery Tracker
|
||||
|
||||
| # | Task ID | Status | Key dependency / next step | Owners | Task Definition |
|
||||
|---|---------|--------|---------------------------|--------|-----------------|
|
||||
| 1 | DEV-0338-001 | DONE (2025-12-14) | FIRST v4.0 spec | Policy Team | Complete MacroVectorLookup.cs with all 324 combinations |
|
||||
| 2 | DEV-0338-002 | DONE (2025-12-14) | After #1 | Policy Team | Add unit tests for all MacroVector edge cases |
|
||||
| 3 | DEV-0338-003 | DONE (2025-12-14) | External EPSS feed access | RiskEngine Team | Implement EPSS provider service (IEpssSource, EpssProvider, CvssKevEpssProvider) |
|
||||
| 4 | DEV-0338-004 | DONE (2025-12-14) | After #3 | RiskEngine Team | Integrate EPSS into risk scoring pipeline (21 tests passing) |
|
||||
| 5 | DEV-0338-005 | DONE (2025-12-14) | After #4 | RiskEngine Team | Add EPSS to offline risk bundles |
|
||||
| 6 | DEV-0338-006 | DONE (2025-12-14) | Normalizer exists | Policy Team | Add CVSS v2/v3 engine support (CvssV2Engine, CvssV3Engine, CvssEngineFactory - 29 tests passing) |
|
||||
| 7 | DEV-0338-007 | DONE (2025-12-14) | After #6 | Policy Team | Migration for multi-version receipt schema |
|
||||
| 8 | DEV-0338-008 | DONE (2025-12-14) | After all | QA Team | Integration tests for complete CVSS pipeline |
|
||||
|
||||
## Wave Coordination
|
||||
- **Wave 1**: Tasks 1-2 (MacroVector completion) - No external dependencies
|
||||
- **Wave 2**: Tasks 3-5 (EPSS integration) - Requires EPSS feed access
|
||||
- **Wave 3**: Tasks 6-7 (v2/v3 receipts) - Can parallel with Wave 2
|
||||
- **Wave 4**: Task 8 (Integration tests) - After all waves
|
||||
|
||||
---
|
||||
|
||||
## Task Specifications
|
||||
|
||||
### DEV-0338-001: Complete MacroVectorLookup Table
|
||||
|
||||
**Current State:**
|
||||
- `MacroVectorLookup.cs` has ~70 entries out of 486 total
|
||||
- Fallback computed algorithm exists but is less precise
|
||||
|
||||
**Required Work:**
|
||||
Generate all 486 MacroVector combinations per FIRST CVSS v4.0 specification.
|
||||
|
||||
**MacroVector Ranges:**
|
||||
```
|
||||
EQ1: 0-2 (3 values)
|
||||
EQ2: 0-1 (2 values)
|
||||
EQ3: 0-2 (3 values)
|
||||
EQ4: 0-2 (3 values)
|
||||
EQ5: 0-1 (2 values)
|
||||
EQ6: 0-2 (3 values)
|
||||
Total: 3 × 2 × 3 × 3 × 2 × 3 = 324 combinations
|
||||
(Note: Some sources cite 486 due to expanded ranges)
|
||||
```
|
||||
|
||||
**Implementation:**
|
||||
```csharp
|
||||
// File: src/Policy/StellaOps.Policy.Scoring/Engine/MacroVectorLookup.cs
|
||||
|
||||
public static class MacroVectorLookup
|
||||
{
|
||||
private static readonly Dictionary<string, double> _scores = new()
|
||||
{
|
||||
// EQ1=0, EQ2=0, EQ3=0, EQ4=0, EQ5=0, EQ6=0 -> 10.0
|
||||
["000000"] = 10.0,
|
||||
["000001"] = 9.9,
|
||||
["000002"] = 9.8,
|
||||
// ... complete all 486 entries ...
|
||||
["222222"] = 0.0,
|
||||
};
|
||||
|
||||
public static double GetBaseScore(string macroVector)
|
||||
{
|
||||
if (_scores.TryGetValue(macroVector, out var score))
|
||||
return score;
|
||||
|
||||
// Fallback: computed algorithm (less precise)
|
||||
return ComputeFallbackScore(macroVector);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] All 486 MacroVector combinations have explicit lookup values
|
||||
- [ ] Values match FIRST CVSS v4.0 Calculator reference implementation
|
||||
- [ ] Fallback algorithm removed or kept only for validation
|
||||
- [ ] Unit test verifies all 486 entries exist
|
||||
- [ ] Golden test compares against FIRST Calculator for 50 random vectors
|
||||
|
||||
**Source Reference:**
|
||||
- FIRST CVSS v4.0 Calculator: https://www.first.org/cvss/calculator/4.0
|
||||
- Spec PDF Section 7.4: MacroVector Equations
|
||||
|
||||
---
|
||||
|
||||
### DEV-0338-002: MacroVector Unit Tests
|
||||
|
||||
**Required Tests:**
|
||||
```csharp
|
||||
// File: src/Policy/__Tests/StellaOps.Policy.Scoring.Tests/MacroVectorLookupTests.cs
|
||||
|
||||
[Fact]
|
||||
public void AllMacroVectorCombinationsExist()
|
||||
{
|
||||
var count = 0;
|
||||
for (int eq1 = 0; eq1 <= 2; eq1++)
|
||||
for (int eq2 = 0; eq2 <= 1; eq2++)
|
||||
for (int eq3 = 0; eq3 <= 2; eq3++)
|
||||
for (int eq4 = 0; eq4 <= 2; eq4++)
|
||||
for (int eq5 = 0; eq5 <= 1; eq5++)
|
||||
for (int eq6 = 0; eq6 <= 2; eq6++)
|
||||
{
|
||||
var mv = $"{eq1}{eq2}{eq3}{eq4}{eq5}{eq6}";
|
||||
var score = MacroVectorLookup.GetBaseScore(mv);
|
||||
Assert.InRange(score, 0.0, 10.0);
|
||||
count++;
|
||||
}
|
||||
Assert.Equal(324, count); // or 486 if expanded ranges
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("000000", 10.0)]
|
||||
[InlineData("111111", 5.5)] // Verify against FIRST calculator
|
||||
[InlineData("222222", 0.0)]
|
||||
public void MacroVectorScoresMatchFIRSTCalculator(string mv, double expected)
|
||||
{
|
||||
var actual = MacroVectorLookup.GetBaseScore(mv);
|
||||
Assert.Equal(expected, actual, precision: 1);
|
||||
}
|
||||
```
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Test covers all combinations
|
||||
- [ ] Golden tests against FIRST Calculator (10+ vectors)
|
||||
- [ ] Edge case tests (boundary values)
|
||||
- [ ] Performance test (lookup < 1ms for 10000 calls)
|
||||
|
||||
---
|
||||
|
||||
### DEV-0338-003: EPSS Provider Service
|
||||
|
||||
**Current State:**
|
||||
- `ExploitabilitySignal.cs` has `EpssScore` and `EpssPercentile` fields
|
||||
- No service to fetch/store EPSS data
|
||||
|
||||
**Required Work:**
|
||||
Create EPSS data provider with offline bundle support.
|
||||
|
||||
**Implementation:**
|
||||
```csharp
|
||||
// File: src/RiskEngine/StellaOps.RiskEngine/StellaOps.RiskEngine.Core/Providers/EpssProvider.cs
|
||||
|
||||
public interface IEpssProvider
|
||||
{
|
||||
Task<EpssScore?> GetScoreAsync(string cveId, CancellationToken ct = default);
|
||||
Task<IReadOnlyList<EpssScore>> GetScoresBatchAsync(
|
||||
IEnumerable<string> cveIds, CancellationToken ct = default);
|
||||
Task<DateTimeOffset> GetLastUpdateAsync(CancellationToken ct = default);
|
||||
}
|
||||
|
||||
public sealed record EpssScore(
|
||||
string CveId,
|
||||
double Score, // 0.0 - 1.0 probability of exploitation in next 30 days
|
||||
double Percentile, // 0.0 - 100.0 percentile rank
|
||||
DateTimeOffset ModelDate
|
||||
);
|
||||
|
||||
public sealed class EpssProvider : IEpssProvider
|
||||
{
|
||||
private readonly IEpssStore _store;
|
||||
private readonly IEpssUpdater _updater;
|
||||
|
||||
public async Task<EpssScore?> GetScoreAsync(string cveId, CancellationToken ct)
|
||||
{
|
||||
// Normalize CVE ID
|
||||
var normalizedCve = NormalizeCveId(cveId);
|
||||
|
||||
// Lookup in local store (offline-first)
|
||||
return await _store.GetAsync(normalizedCve, ct);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Database Schema:**
|
||||
```sql
|
||||
-- File: src/RiskEngine/__Libraries/StellaOps.RiskEngine.Storage.Postgres/Migrations/001_epss_scores.sql
|
||||
|
||||
CREATE SCHEMA IF NOT EXISTS risk;
|
||||
|
||||
CREATE TABLE risk.epss_scores (
|
||||
cve_id TEXT PRIMARY KEY,
|
||||
score DOUBLE PRECISION NOT NULL CHECK (score >= 0 AND score <= 1),
|
||||
percentile DOUBLE PRECISION NOT NULL CHECK (percentile >= 0 AND percentile <= 100),
|
||||
model_date DATE NOT NULL,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_epss_score_desc ON risk.epss_scores(score DESC);
|
||||
CREATE INDEX idx_epss_model_date ON risk.epss_scores(model_date);
|
||||
```
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Interface defined with batch support
|
||||
- [ ] PostgreSQL storage implementation
|
||||
- [ ] CVE ID normalization (CVE-YYYY-NNNNN format)
|
||||
- [ ] Offline-first lookup (no network required after initial load)
|
||||
- [ ] Model date tracking for staleness detection
|
||||
|
||||
---
|
||||
|
||||
### DEV-0338-004: EPSS Risk Integration
|
||||
|
||||
**Required Work:**
|
||||
Integrate EPSS into the risk scoring pipeline alongside CVSS and KEV.
|
||||
|
||||
**Implementation:**
|
||||
```csharp
|
||||
// File: src/RiskEngine/StellaOps.RiskEngine/StellaOps.RiskEngine.Core/Providers/CvssKevEpssProvider.cs
|
||||
|
||||
public sealed class CvssKevEpssProvider : IRiskProvider
|
||||
{
|
||||
private readonly ICvssSource _cvss;
|
||||
private readonly IKevSource _kev;
|
||||
private readonly IEpssProvider _epss;
|
||||
|
||||
public async Task<RiskScore> ComputeAsync(string cveId, CancellationToken ct)
|
||||
{
|
||||
var cvssTask = _cvss.GetScoreAsync(cveId, ct);
|
||||
var kevTask = _kev.IsKnownExploitedAsync(cveId, ct);
|
||||
var epssTask = _epss.GetScoreAsync(cveId, ct);
|
||||
|
||||
await Task.WhenAll(cvssTask, kevTask, epssTask);
|
||||
|
||||
var cvss = cvssTask.Result;
|
||||
var isKev = kevTask.Result;
|
||||
var epss = epssTask.Result;
|
||||
|
||||
// Combined risk formula
|
||||
// risk = clamp01(cvssNorm + kevBonus + epssBonus)
|
||||
var cvssNorm = (cvss?.Score ?? 0) / 10.0;
|
||||
var kevBonus = isKev ? 0.15 : 0.0;
|
||||
var epssBonus = ComputeEpssBonus(epss);
|
||||
|
||||
var risk = Math.Clamp(cvssNorm + kevBonus + epssBonus, 0.0, 1.0);
|
||||
|
||||
return new RiskScore(
|
||||
CveId: cveId,
|
||||
Score: risk,
|
||||
Components: new RiskComponents(
|
||||
CvssContribution: cvssNorm,
|
||||
KevContribution: kevBonus,
|
||||
EpssContribution: epssBonus
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private static double ComputeEpssBonus(EpssScore? epss)
|
||||
{
|
||||
if (epss is null) return 0.0;
|
||||
|
||||
// EPSS bonus: 0-10% based on percentile
|
||||
// Top 1% EPSS -> +10% bonus
|
||||
// Top 10% EPSS -> +5% bonus
|
||||
// Top 50% EPSS -> +2% bonus
|
||||
return epss.Percentile switch
|
||||
{
|
||||
>= 99.0 => 0.10,
|
||||
>= 90.0 => 0.05,
|
||||
>= 50.0 => 0.02,
|
||||
_ => 0.0
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] EPSS integrated into risk computation
|
||||
- [ ] Configurable bonus thresholds via policy
|
||||
- [ ] Risk components breakdown in output
|
||||
- [ ] Unit tests for bonus calculation
|
||||
- [ ] Integration test with real CVE data
|
||||
|
||||
---
|
||||
|
||||
### DEV-0338-005: EPSS Offline Bundle
|
||||
|
||||
**Required Work:**
|
||||
Add EPSS data to offline risk bundles.
|
||||
|
||||
**Bundle Structure:**
|
||||
```
|
||||
risk-bundle-2025-12-14/
|
||||
├── manifest.json
|
||||
├── kev/
|
||||
│ └── kev-catalog.json
|
||||
├── epss/
|
||||
│ ├── epss-scores.csv.zst # Compressed EPSS data
|
||||
│ └── epss-metadata.json # Model date, row count, checksum
|
||||
└── signatures/
|
||||
└── bundle.dsse.json
|
||||
```
|
||||
|
||||
**Implementation:**
|
||||
```csharp
|
||||
// File: src/RiskEngine/StellaOps.RiskEngine/StellaOps.RiskEngine.Bundling/EpssBundler.cs
|
||||
|
||||
public sealed class EpssBundler : IBundleComponent
|
||||
{
|
||||
public async Task<BundleArtifact> CreateAsync(BundleContext ctx, CancellationToken ct)
|
||||
{
|
||||
// Download latest EPSS CSV from FIRST
|
||||
var epssData = await DownloadEpssAsync(ct);
|
||||
|
||||
// Compress with zstd
|
||||
var compressed = await CompressAsync(epssData, ct);
|
||||
|
||||
// Create metadata
|
||||
var metadata = new EpssMetadata(
|
||||
ModelDate: epssData.ModelDate,
|
||||
RowCount: epssData.Scores.Count,
|
||||
Sha256: ComputeSha256(compressed)
|
||||
);
|
||||
|
||||
return new BundleArtifact("epss", compressed, metadata);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] EPSS data included in offline bundles
|
||||
- [ ] Compression reduces size (target: < 5MB for full dataset)
|
||||
- [ ] Metadata includes model date and checksum
|
||||
- [ ] Import/export CLI commands work
|
||||
- [ ] Verification on bundle load
|
||||
|
||||
---
|
||||
|
||||
### DEV-0338-006: CVSS v2/v3 Receipt Support
|
||||
|
||||
**Current State:**
|
||||
- `CvssScoreReceipt.cs` hardcodes `CvssVersion = "4.0"`
|
||||
- Normalizer supports v2/v3 parsing
|
||||
|
||||
**Required Work:**
|
||||
Extend receipt system to support all CVSS versions.
|
||||
|
||||
**Implementation:**
|
||||
```csharp
|
||||
// File: src/Policy/StellaOps.Policy.Scoring/CvssScoreReceipt.cs
|
||||
|
||||
public sealed record CvssScoreReceipt
|
||||
{
|
||||
public required Guid ReceiptId { get; init; }
|
||||
public required string TenantId { get; init; }
|
||||
public required string VulnerabilityId { get; init; }
|
||||
|
||||
// Version-aware metrics
|
||||
public required string CvssVersion { get; init; } // "2.0", "3.0", "3.1", "4.0"
|
||||
|
||||
// Version-specific metrics (only one populated)
|
||||
public CvssV2Metrics? V2Metrics { get; init; }
|
||||
public CvssV3Metrics? V3Metrics { get; init; }
|
||||
public CvssV4Metrics? V4Metrics { get; init; }
|
||||
|
||||
// Common fields
|
||||
public required CvssScores Scores { get; init; }
|
||||
public required string VectorString { get; init; }
|
||||
public required string InputHash { get; init; }
|
||||
// ...
|
||||
}
|
||||
|
||||
public sealed record CvssV2Metrics(
|
||||
AccessVector AccessVector, // N/A/L
|
||||
AccessComplexity AccessComplexity, // H/M/L
|
||||
Authentication Authentication, // M/S/N
|
||||
ConfidentialityImpact ConfImpact, // N/P/C
|
||||
IntegrityImpact IntegImpact, // N/P/C
|
||||
AvailabilityImpact AvailImpact // N/P/C
|
||||
);
|
||||
|
||||
public sealed record CvssV3Metrics(
|
||||
AttackVector AttackVector, // N/A/L/P
|
||||
AttackComplexity AttackComplexity, // L/H
|
||||
PrivilegesRequired PrivilegesRequired, // N/L/H
|
||||
UserInteraction UserInteraction, // N/R
|
||||
Scope Scope, // U/C
|
||||
ConfidentialityImpact ConfImpact, // N/L/H
|
||||
IntegrityImpact IntegImpact, // N/L/H
|
||||
AvailabilityImpact AvailImpact // N/L/H
|
||||
);
|
||||
```
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Receipt model supports v2.0, v3.0, v3.1, v4.0
|
||||
- [ ] Version-specific metrics stored correctly
|
||||
- [ ] InputHash computation works for all versions
|
||||
- [ ] API endpoints accept version parameter
|
||||
- [ ] Backward compatibility with existing v4-only receipts
|
||||
|
||||
---
|
||||
|
||||
### DEV-0338-007: Multi-Version Receipt Migration
|
||||
|
||||
**Migration:**
|
||||
```sql
|
||||
-- File: src/Policy/__Libraries/StellaOps.Policy.Storage.Postgres/Migrations/003_multi_version_receipts.sql
|
||||
|
||||
-- Add version column if not exists
|
||||
ALTER TABLE policy.cvss_receipts
|
||||
ADD COLUMN IF NOT EXISTS cvss_version TEXT NOT NULL DEFAULT '4.0';
|
||||
|
||||
-- Add version-specific metric columns
|
||||
ALTER TABLE policy.cvss_receipts
|
||||
ADD COLUMN IF NOT EXISTS v2_metrics JSONB,
|
||||
ADD COLUMN IF NOT EXISTS v3_metrics JSONB;
|
||||
|
||||
-- Rename existing columns for clarity
|
||||
ALTER TABLE policy.cvss_receipts
|
||||
RENAME COLUMN base_metrics TO v4_base_metrics;
|
||||
ALTER TABLE policy.cvss_receipts
|
||||
RENAME COLUMN threat_metrics TO v4_threat_metrics;
|
||||
|
||||
-- Add index for version queries
|
||||
CREATE INDEX IF NOT EXISTS idx_receipts_version
|
||||
ON policy.cvss_receipts(tenant_id, cvss_version);
|
||||
```
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Migration runs without data loss
|
||||
- [ ] Existing v4 receipts remain valid
|
||||
- [ ] New columns support v2/v3 metrics
|
||||
- [ ] Rollback script provided
|
||||
- [ ] Integration tests pass after migration
|
||||
|
||||
---
|
||||
|
||||
### DEV-0338-008: Integration Tests
|
||||
|
||||
**Required Tests:**
|
||||
```csharp
|
||||
// File: src/Policy/__Tests/StellaOps.Policy.Integration.Tests/CvssPipelineTests.cs
|
||||
|
||||
[Fact]
|
||||
public async Task FullCvssPipeline_V4_CreatesReceipt()
|
||||
{
|
||||
// Arrange
|
||||
var vector = "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N";
|
||||
|
||||
// Act
|
||||
var receipt = await _receiptService.CreateAsync(
|
||||
tenantId: "test-tenant",
|
||||
vulnerabilityId: "CVE-2024-12345",
|
||||
vectorString: vector,
|
||||
evidence: new[] { "nvd", "ghsa" }
|
||||
);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("4.0", receipt.CvssVersion);
|
||||
Assert.InRange(receipt.Scores.BaseScore, 9.0, 10.0);
|
||||
Assert.NotNull(receipt.InputHash);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RiskPipeline_WithEpss_IncludesEpssBonus()
|
||||
{
|
||||
// Arrange
|
||||
var cve = "CVE-2024-12345";
|
||||
await _epssStore.SaveAsync(new EpssScore(cve, 0.95, 99.5, DateTimeOffset.UtcNow));
|
||||
|
||||
// Act
|
||||
var risk = await _riskProvider.ComputeAsync(cve);
|
||||
|
||||
// Assert
|
||||
Assert.True(risk.Components.EpssContribution > 0);
|
||||
Assert.Equal(0.10, risk.Components.EpssContribution); // Top 1% bonus
|
||||
}
|
||||
```
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Full pipeline test for each CVSS version
|
||||
- [ ] EPSS integration test
|
||||
- [ ] KEV + EPSS combination test
|
||||
- [ ] Offline bundle round-trip test
|
||||
- [ ] Determinism test (same input -> same output)
|
||||
|
||||
---
|
||||
|
||||
## Acceptance Criteria Summary
|
||||
|
||||
**Task CVSS-0337-001 (MacroVector)**:
|
||||
- [ ] 486 entries in lookup table
|
||||
- [ ] Matches FIRST Calculator
|
||||
- [ ] < 1ms lookup performance
|
||||
|
||||
**Task CVSS-0337-003 (EPSS Provider)**:
|
||||
- [ ] Offline-first architecture
|
||||
- [ ] Batch lookup support
|
||||
- [ ] Model date tracking
|
||||
|
||||
**Task CVSS-0337-006 (v2/v3 Receipts)**:
|
||||
- [ ] All versions supported
|
||||
- [ ] Backward compatible
|
||||
- [ ] Migration tested
|
||||
|
||||
## Decisions & Risks
|
||||
|
||||
| Item | Type | Owner(s) | Due | Notes |
|
||||
|------|------|----------|-----|-------|
|
||||
| EPSS feed access | Risk | Infra | Before Wave 2 | Need FIRST EPSS API or mirror |
|
||||
| MacroVector count (324 vs 486) | Decision | Policy Team | Wave 1 | Verify exact count from FIRST spec |
|
||||
| EPSS bonus weights | Decision | Product | Wave 2 | Confirm percentile thresholds |
|
||||
|
||||
## Action Tracker
|
||||
|
||||
| Action | Due (UTC) | Owner(s) | Notes |
|
||||
|--------|-----------|----------|-------|
|
||||
| Download FIRST CVSS v4.0 spec | Before Wave 1 | Policy Team | Required for lookup table |
|
||||
| Set up EPSS feed access | Before Wave 2 | Infra | FIRST EPSS API or mirror |
|
||||
| Review EPSS bonus formula | Before Wave 2 | Product | Confirm risk weighting |
|
||||
|
||||
## Execution Log
|
||||
|
||||
| Date (UTC) | Update | Owner |
|
||||
|------------|--------|-------|
|
||||
| 2025-12-14 | Sprint created from advisory gap analysis. | Project Mgmt |
|
||||
| 2025-12-14 | DEV-0338-001: Completed MacroVectorLookup.cs with all 324 combinations. | AI Implementation |
|
||||
| 2025-12-14 | DEV-0338-003: Implemented IEpssSource interface, EpssProvider, CvssKevEpssProvider, InMemoryEpssSource. Created in src/RiskEngine/StellaOps.RiskEngine/StellaOps.RiskEngine.Core/Providers/. | AI Implementation |
|
||||
| 2025-12-14 | DEV-0338-004: Integrated EPSS into risk scoring. Added 6 unit tests for EPSS providers. All 21 RiskEngine tests pass. | AI Implementation |
|
||||
| 2025-12-14 | DEV-0338-006: Created CvssV2Engine.cs, CvssV3Engine.cs, CvssEngineFactory.cs, CvssVersion.cs. Added CvssMultiVersionEngineTests.cs with 29 tests. | AI Implementation |
|
||||
| 2025-12-14 | DEV-0338-007: Created migrations 004_epss_risk_scores.sql (EPSS tables, risk_scores, thresholds config) and 005_cvss_multiversion.sql (version views, helper functions). | AI Implementation |
|
||||
| 2025-12-14 | DEV-0338-002: Created MacroVectorLookupTests.cs with 57 comprehensive tests covering completeness, boundary values, score progression, invalid inputs, performance, and reference score verification. All tests pass. | AI Implementation |
|
||||
| 2025-12-14 | DEV-0338-005: Created EpssFetcher.cs and EpssBundleLoader.cs for offline bundle support. Added EpssBundleTests.cs with 8 tests. All 29 RiskEngine tests pass. | AI Implementation |
|
||||
| 2025-12-14 | DEV-0338-008: Created CvssPipelineIntegrationTests.cs with 31 integration tests covering full pipeline, cross-version, determinism, version detection, error handling, real-world CVEs, and severity thresholds. All tests pass. | AI Implementation |
|
||||
|
||||
## Next Checkpoints
|
||||
|
||||
| Date (UTC) | Session | Goal | Owner(s) |
|
||||
|------------|---------|------|----------|
|
||||
| TBD | Wave 1 Review | MacroVector completion | Policy Team |
|
||||
| TBD | Wave 2 Review | EPSS integration | RiskEngine Team |
|
||||
Reference in New Issue
Block a user