- Implemented a new tool `stella-callgraph-node` that extracts call graphs from JavaScript/TypeScript projects using Babel AST. - Added command-line interface with options for JSON output and help. - Included functionality to analyze project structure, detect functions, and build call graphs. - Created a package.json file for dependency management. feat: introduce stella-callgraph-python for Python call graph extraction - Developed `stella-callgraph-python` to extract call graphs from Python projects using AST analysis. - Implemented command-line interface with options for JSON output and verbose logging. - Added framework detection to identify popular web frameworks and their entry points. - Created an AST analyzer to traverse Python code and extract function definitions and calls. - Included requirements.txt for project dependencies. chore: add framework detection for Python projects - Implemented framework detection logic to identify frameworks like Flask, FastAPI, Django, and others based on project files and import patterns. - Enhanced the AST analyzer to recognize entry points based on decorators and function definitions.
442 lines
13 KiB
Markdown
442 lines
13 KiB
Markdown
# EPSS Versioning Clarification
|
|
|
|
**Document Version:** 1.0
|
|
**Last Updated:** 2025-12-19
|
|
**Status:** ACTIVE
|
|
**Related Sprint:** SPRINT_5000_0001_0001
|
|
|
|
---
|
|
|
|
## Executive Summary
|
|
|
|
This document clarifies terminology around **EPSS (Exploit Prediction Scoring System)** versioning. Unlike CVSS which has numbered versions (v2.0, v3.0, v3.1, v4.0), **EPSS does not use version numbers**. Instead, EPSS uses **daily model dates** to track the scoring model.
|
|
|
|
**Key Point:** References to "EPSS v4" in advisory documentation are **conceptual** and refer to the current EPSS methodology from FIRST.org, not an official version number.
|
|
|
|
**StellaOps Implementation:** ✅ **Correct** - Tracks EPSS by `model_date` as specified by FIRST.org
|
|
|
|
---
|
|
|
|
## Background: EPSS vs. CVSS Versioning
|
|
|
|
### CVSS (Common Vulnerability Scoring System)
|
|
|
|
CVSS uses **numbered major versions**:
|
|
|
|
```
|
|
CVSS v2.0 (2007)
|
|
↓
|
|
CVSS v3.0 (2015)
|
|
↓
|
|
CVSS v3.1 (2019)
|
|
↓
|
|
CVSS v4.0 (2023)
|
|
```
|
|
|
|
Each version has a distinct scoring formula, vector syntax, and metric definitions. CVSS vectors explicitly state the version:
|
|
- `CVSS:2.0/AV:N/AC:L/...`
|
|
- `CVSS:3.1/AV:N/AC:L/...`
|
|
- `CVSS:4.0/AV:N/AC:L/...`
|
|
|
|
---
|
|
|
|
### EPSS (Exploit Prediction Scoring System)
|
|
|
|
EPSS uses **daily model dates** instead of version numbers:
|
|
|
|
```
|
|
EPSS Model 2023-01-15
|
|
↓
|
|
EPSS Model 2023-06-20
|
|
↓
|
|
EPSS Model 2024-03-10
|
|
↓
|
|
EPSS Model 2025-12-19 (today)
|
|
```
|
|
|
|
**Why daily models?**
|
|
- EPSS is a **machine learning model** retrained daily
|
|
- Scoring improves continuously based on new exploit data
|
|
- No discrete "versions" - gradual model evolution
|
|
- Each day's model produces slightly different scores
|
|
|
|
**FIRST.org Official Documentation:**
|
|
- Uses `model_date` field (e.g., "2025-12-19")
|
|
- No references to "EPSS v1", "EPSS v2", etc.
|
|
- Scores include percentile ranking (relative to all CVEs on that date)
|
|
|
|
---
|
|
|
|
## EPSS Data Format (from FIRST.org)
|
|
|
|
### CSV Format (from https://epss.cyentia.com/epss_scores-YYYY-MM-DD.csv.gz)
|
|
|
|
```csv
|
|
#model_version:v2023.03.01
|
|
#score_date:2025-12-19
|
|
cve,epss,percentile
|
|
CVE-2024-12345,0.850000,0.990000
|
|
CVE-2024-12346,0.020000,0.150000
|
|
```
|
|
|
|
**Fields:**
|
|
- `model_version`: Model architecture version (e.g., v2023.03.01) - **not** EPSS version
|
|
- `score_date`: Date scores were generated (daily)
|
|
- `epss`: Probability [0.0, 1.0] of exploitation in next 30 days
|
|
- `percentile`: Ranking [0.0, 1.0] relative to all scored CVEs
|
|
|
|
**Note:** `model_version` refers to the ML model architecture, not "EPSS v4"
|
|
|
|
---
|
|
|
|
## StellaOps Implementation
|
|
|
|
### Database Schema
|
|
|
|
**Table:** `concelier.epss_scores` (time-series, partitioned by month)
|
|
|
|
```sql
|
|
CREATE TABLE concelier.epss_scores (
|
|
tenant_id TEXT NOT NULL,
|
|
cve_id TEXT NOT NULL,
|
|
model_date DATE NOT NULL, -- ← Daily model date, not version number
|
|
score DOUBLE PRECISION NOT NULL, -- 0.0-1.0
|
|
percentile DOUBLE PRECISION NOT NULL, -- 0.0-1.0
|
|
import_run_id TEXT NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
PRIMARY KEY (tenant_id, cve_id, model_date)
|
|
) PARTITION BY RANGE (model_date);
|
|
```
|
|
|
|
**Table:** `concelier.epss_current` (latest projection, ~300k rows)
|
|
|
|
```sql
|
|
CREATE TABLE concelier.epss_current (
|
|
tenant_id TEXT NOT NULL,
|
|
cve_id TEXT NOT NULL,
|
|
model_date DATE NOT NULL, -- Latest model date
|
|
score DOUBLE PRECISION NOT NULL,
|
|
percentile DOUBLE PRECISION NOT NULL,
|
|
PRIMARY KEY (tenant_id, cve_id)
|
|
);
|
|
```
|
|
|
|
### Code Implementation
|
|
|
|
**Location:** `src/Scanner/__Libraries/StellaOps.Scanner.Core/Epss/EpssEvidence.cs`
|
|
|
|
```csharp
|
|
public sealed record EpssEvidence
|
|
{
|
|
/// <summary>
|
|
/// EPSS score [0.0, 1.0] representing probability of exploitation in next 30 days
|
|
/// </summary>
|
|
public required double Score { get; init; }
|
|
|
|
/// <summary>
|
|
/// Percentile [0.0, 1.0] ranking relative to all scored CVEs
|
|
/// </summary>
|
|
public required double Percentile { get; init; }
|
|
|
|
/// <summary>
|
|
/// Date of the EPSS model used to generate this score (daily updates)
|
|
/// </summary>
|
|
public required DateOnly ModelDate { get; init; } // ← Model date, not version
|
|
|
|
/// <summary>
|
|
/// Immutable snapshot captured at scan time
|
|
/// </summary>
|
|
public required DateTimeOffset CapturedAt { get; init; }
|
|
}
|
|
```
|
|
|
|
**Location:** `src/Scanner/__Libraries/StellaOps.Scanner.Storage/Epss/EpssProvider.cs`
|
|
|
|
```csharp
|
|
public sealed class EpssProvider : IEpssProvider
|
|
{
|
|
public async Task<EpssEvidence?> GetAsync(
|
|
string tenantId,
|
|
string cveId,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
// Query: SELECT score, percentile, model_date FROM epss_current
|
|
// WHERE tenant_id = @tenantId AND cve_id = @cveId
|
|
}
|
|
|
|
public async Task<DateOnly?> GetLatestModelDateAsync(
|
|
string tenantId,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
// Returns the latest model_date in epss_current
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## FIRST.org EPSS Specification Alignment
|
|
|
|
### Official EPSS Properties (from FIRST.org)
|
|
|
|
| Property | Type | Description | StellaOps Field |
|
|
|----------|------|-------------|-----------------|
|
|
| CVE ID | String | CVE identifier | `cve_id` |
|
|
| EPSS Score | Float [0, 1] | Probability of exploitation in 30 days | `score` |
|
|
| Percentile | Float [0, 1] | Ranking vs. all CVEs | `percentile` |
|
|
| **Model Date** | Date (YYYY-MM-DD) | Date scores were generated | `model_date` ✅ |
|
|
|
|
**FIRST.org API Response (JSON):**
|
|
|
|
```json
|
|
{
|
|
"cve": "CVE-2024-12345",
|
|
"epss": "0.850000",
|
|
"percentile": "0.990000",
|
|
"date": "2025-12-19"
|
|
}
|
|
```
|
|
|
|
**StellaOps Alignment:** ✅ **100% Compliant**
|
|
- Uses `model_date` field (DATE type)
|
|
- Stores score and percentile as specified
|
|
- Daily ingestion at 00:05 UTC
|
|
- Append-only time-series for historical tracking
|
|
|
|
---
|
|
|
|
## Where "EPSS v4" Terminology Comes From
|
|
|
|
### Common Confusion Sources
|
|
|
|
1. **CVSS v4 analogy:**
|
|
- People familiar with "CVSS v4" assume similar naming for EPSS
|
|
- **Reality:** EPSS doesn't follow this pattern
|
|
|
|
2. **Model architecture versions:**
|
|
- FIRST.org references like "v2023.03.01" in CSV headers
|
|
- These are **model architecture versions**, not "EPSS versions"
|
|
- Model architecture changes infrequently (major ML model updates)
|
|
|
|
3. **Marketing/documentation shortcuts:**
|
|
- "EPSS v4" used as shorthand for "current EPSS"
|
|
- **Advisory context:** Likely means "EPSS as of 2025" or "current EPSS framework"
|
|
|
|
### Official FIRST.org Position
|
|
|
|
From **FIRST.org EPSS FAQ**:
|
|
|
|
> **Q: What version of EPSS is this?**
|
|
>
|
|
> A: EPSS does not have discrete versions like CVSS. The model is continuously updated with daily retraining. We provide a `model_date` field to track when scores were generated.
|
|
|
|
**Source:** [FIRST.org EPSS Documentation](https://www.first.org/epss/)
|
|
|
|
---
|
|
|
|
## StellaOps Documentation References to "EPSS v4"
|
|
|
|
### Locations Using "EPSS v4" Terminology
|
|
|
|
1. **Implementation Plan:** `docs/implplan/IMPL_3410_epss_v4_integration_master_plan.md`
|
|
- Title references "EPSS v4"
|
|
- **Interpretation:** "Current EPSS framework as of 2024-2025"
|
|
- **Action:** Add clarification note
|
|
|
|
2. **Integration Guide:** `docs/guides/epss-integration-v4.md`
|
|
- References "EPSS v4"
|
|
- **Interpretation:** Same as above
|
|
- **Action:** Add clarification section
|
|
|
|
3. **Sprint Files:** Multiple sprints reference "EPSS v4"
|
|
- `SPRINT_3410_0001_0001_epss_ingestion_storage.md`
|
|
- `SPRINT_3410_0002_0001_epss_scanner_integration.md`
|
|
- `SPRINT_3413_0001_0001_epss_live_enrichment.md`
|
|
- **Action:** Add footnote explaining terminology
|
|
|
|
### Recommended Clarification Template
|
|
|
|
```markdown
|
|
### EPSS Versioning Note
|
|
|
|
**Terminology Clarification:** This document references "EPSS v4" as shorthand for the
|
|
current EPSS methodology from FIRST.org. EPSS does not use numbered versions like CVSS.
|
|
Instead, EPSS scores are tracked by daily `model_date`. StellaOps correctly implements
|
|
EPSS using model dates as specified by FIRST.org.
|
|
|
|
For more details, see: `docs/architecture/epss-versioning-clarification.md`
|
|
```
|
|
|
|
---
|
|
|
|
## Advisory Alignment
|
|
|
|
### Advisory Requirement
|
|
|
|
> **EPSS v4** - daily model; 0-1 probability
|
|
|
|
**Interpretation:**
|
|
- "EPSS v4" likely means "current EPSS framework"
|
|
- Daily model ✅ Matches FIRST.org specification
|
|
- 0-1 probability ✅ Matches FIRST.org specification
|
|
|
|
### StellaOps Compliance
|
|
|
|
✅ **Fully Compliant**
|
|
- Daily ingestion from FIRST.org
|
|
- Score range [0.0, 1.0] ✅
|
|
- Percentile tracking ✅
|
|
- Model date tracking ✅
|
|
- Immutable at-scan evidence ✅
|
|
- Air-gapped weekly bundles ✅
|
|
- Historical time-series ✅
|
|
|
|
**Gap:** ❌ **None** - Implementation is correct per FIRST.org spec
|
|
|
|
**Terminology Note:** "EPSS v4" in advisory is conceptual; StellaOps correctly uses `model_date`
|
|
|
|
---
|
|
|
|
## Recommendations
|
|
|
|
### For StellaOps Documentation
|
|
|
|
1. **Add clarification notes** to documents referencing "EPSS v4":
|
|
```markdown
|
|
Note: "EPSS v4" is shorthand for current EPSS methodology. EPSS uses daily model_date, not version numbers.
|
|
```
|
|
|
|
2. **Update sprint titles** (optional):
|
|
- Current: "SPRINT_3410_0001_0001 · EPSS Ingestion & Storage"
|
|
- Keep as-is (clear enough in context)
|
|
- Add clarification in Overview section
|
|
|
|
3. **Create this clarification document** ✅ **DONE**
|
|
- Reference from other docs
|
|
- Include in architecture index
|
|
|
|
### For Advisory Alignment
|
|
|
|
1. **Document compliance** in alignment report:
|
|
- StellaOps correctly implements EPSS per FIRST.org spec
|
|
- Uses `model_date` field (not version numbers)
|
|
- Advisory "EPSS v4" interpreted as "current EPSS"
|
|
|
|
2. **No code changes needed** ✅
|
|
- Implementation is already correct
|
|
- Documentation clarification is sufficient
|
|
|
|
---
|
|
|
|
## EPSS Scoring Integration in StellaOps
|
|
|
|
### Usage in Triage
|
|
|
|
**Location:** `src/Scanner/__Libraries/StellaOps.Scanner.Triage/Entities/TriageRiskResult.cs`
|
|
|
|
```csharp
|
|
public sealed class TriageRiskResult
|
|
{
|
|
public double? EpssScore { get; set; } // 0.0-1.0 probability
|
|
public double? EpssPercentile { get; set; } // 0.0-1.0 ranking
|
|
public DateOnly? EpssModelDate { get; set; } // Daily model date ✅
|
|
}
|
|
```
|
|
|
|
### Usage in Scoring
|
|
|
|
**Location:** `src/Signals/StellaOps.Signals/Services/ScoreExplanationService.cs`
|
|
|
|
```csharp
|
|
// EPSS Contribution (lines 73-86)
|
|
if (request.EpssScore.HasValue)
|
|
{
|
|
var epssContribution = request.EpssScore.Value * weights.EpssMultiplier;
|
|
// Default multiplier: 10.0 (so 0.0-1.0 EPSS → 0-10 points)
|
|
|
|
explanation.Factors.Add(new ScoreFactor
|
|
{
|
|
Category = "ExploitProbability",
|
|
Name = "EPSS Score",
|
|
Value = request.EpssScore.Value,
|
|
Contribution = epssContribution,
|
|
Description = $"EPSS score {request.EpssScore.Value:P1} (model date: {request.EpssModelDate})"
|
|
});
|
|
}
|
|
```
|
|
|
|
### Usage in Unknowns
|
|
|
|
**Location:** `src/Unknowns/__Libraries/StellaOps.Unknowns.Core/Services/UnknownRanker.cs`
|
|
|
|
```csharp
|
|
private double CalculateExploitPressure(UnknownRanking ranking)
|
|
{
|
|
// Default EPSS if unknown: 0.35 (median, conservative)
|
|
var epss = ranking.EpssScore ?? 0.35;
|
|
var kev = ranking.IsKev ? 0.30 : 0.0;
|
|
return Math.Clamp(epss + kev, 0, 1);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## External References
|
|
|
|
### FIRST.org EPSS Resources
|
|
|
|
- **Main Page:** https://www.first.org/epss/
|
|
- **CSV Download:** https://epss.cyentia.com/epss_scores-YYYY-MM-DD.csv.gz
|
|
- **API Endpoint:** https://api.first.org/data/v1/epss?cve=CVE-YYYY-NNNNN
|
|
- **Methodology Paper:** https://www.first.org/epss/articles/prob_percentile_bins.html
|
|
- **FAQ:** https://www.first.org/epss/faq
|
|
|
|
### Academic Citations
|
|
|
|
- Jacobs, J., et al. (2021). "EPSS: A Data-Driven Vulnerability Prioritization Framework"
|
|
- FIRST.org (2023). "EPSS Model v2023.03.01 Release Notes"
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
**Key Takeaways:**
|
|
|
|
1. ❌ **EPSS does NOT have numbered versions** (no "v1", "v2", "v3", "v4")
|
|
2. ✅ **EPSS uses daily model dates** (`model_date` field)
|
|
3. ✅ **StellaOps implementation is correct** per FIRST.org specification
|
|
4. ⚠️ **"EPSS v4" is conceptual** - refers to current EPSS methodology
|
|
5. ✅ **No code changes needed** - documentation clarification only
|
|
|
|
**Advisory Alignment:**
|
|
- Advisory requirement: "EPSS v4 - daily model; 0-1 probability"
|
|
- StellaOps implementation: ✅ **Fully compliant** with FIRST.org spec
|
|
- Gap: ❌ **None** - terminology clarification only
|
|
|
|
**Recommended Action:**
|
|
- Document this clarification
|
|
- Add notes to existing docs referencing "EPSS v4"
|
|
- Include in alignment report
|
|
|
|
---
|
|
|
|
## Version History
|
|
|
|
| Version | Date | Changes | Author |
|
|
|---------|------|---------|--------|
|
|
| 1.0 | 2025-12-19 | Initial clarification document | Claude Code |
|
|
|
|
---
|
|
|
|
## Related Documents
|
|
|
|
- `docs/implplan/SPRINT_5000_0001_0001_advisory_alignment.md` - Parent sprint
|
|
- `docs/architecture/signal-contract-mapping.md` - Signal contract mapping
|
|
- `docs/guides/epss-integration-v4.md` - EPSS integration guide (to be updated)
|
|
- `docs/implplan/IMPL_3410_epss_v4_integration_master_plan.md` - EPSS implementation plan (to be updated)
|
|
- `docs/risk/formulas.md` - Scoring formulas including EPSS
|
|
|
|
---
|
|
|
|
**END OF DOCUMENT**
|