EPSS - Exploit Prediction Scoring System
EPSS (Exploit Prediction Scoring System) is a data-driven model developed by FIRST (Forum of Incident Response and Security Teams) that calculates the probability that a CVE will be actively exploited in the wild within the next 30 days. EPSS supplements CVSS (which only assesses severity) by incorporating a probability of exploitation, thereby enabling risk-based prioritization.
EPSS solves the biggest problem in vulnerability management: prioritization. A company with 5,000 open CVEs cannot patch them all at once. A CVSS score of 10.0 indicates "maximum severity"—but not "currently being actively exploited." EPSS answers exactly this question: Which CVEs are being actively exploited RIGHT NOW, this week?
EPSS vs. CVSS
CVSS (Common Vulnerability Scoring System):
- Measures: technical severity of the vulnerability
- Question: "How bad would it be IF exploited?"
- No information on exploitation probability
- Criticism: almost all Critical CVEs have CVSS 9.0–10.0 → no differentiation
EPSS:
- Measures: Probability of active exploitation in the next 30 days
- Question: "Is this CVE LIKELY to be exploited?"
- Scale: 0.0–1.0 (0% to 100% probability)
- Updated daily (new exploit data is incorporated)
- Created by: FIRST (Forum of Incident Response and Security Teams)
Combined Approach (CTEM Standard): Prioritization = CVSS + EPSS + Exposure + Business Impact
| CVSS | EPSS | Exposure | Recommendation |
|---|---|---|---|
| High | High | Internet-facing | Patch IMMEDIATELY! |
| High | Low | Internal | Regular patch cycle |
| Low | High | Internet-facing | Patch soon (being exploited!) |
| Low | Low | Internal | Low Priority |
Key Statistic: Only 4% of all CVEs are ever actively exploited (FIRST data) – 96% of patches prioritized by CVSS would never have been necessary. EPSS identifies the relevant 4% early on.
EPSS Model and Data Sources
Data Sources (Inputs):
- CVE metadata (severity, type, age, attacker complexity)
- Exploit code: ExploitDB, Metasploit, GitHub Security Advisories
- Scanning activity: Shodan, Shadowserver (observed scans)
- Darknet activity: exploit sales, usage signals
- Security vendor feeds: vendor reports on active exploitation
ML model:
- Gradient Boosting (XGBoost-like)
- ~1,500 features per CVE
- Training: historical exploit data (what was actually exploited?)
- Daily recalculation: new exploits → immediate score increase
- Validation: Recall, Precision, F1-Score
EPSS Score Interpretation:
| Score | Meaning |
|---|---|
| > 0.90 (90%) | Very high probability - will be exploited this week! |
| 0.50–0.90 | High probability – treat as a priority |
| 0.10–0.50 | Moderate probability – include in patch cycles |
| 0.01–0.10 | Low probability – standard prioritization |
| < 0.01 (1%) | Very low probability – low priority |
Known examples:
- CVE-2021-44228 (Log4Shell): EPSS shortly after publication: 0.97 (97%) → immediately highest priority – correct assessment
- CVE-2023-22515 (Atlassian Confluence RCE): EPSS: 0.96 (96%) after patch release → actively exploited before many had patched
Using the EPSS API
FIRST EPSS API (free, no authentication):
# Query a single CVE:
curl "https://api.first.org/data/v1/epss?cve=CVE-2021-44228"
# Multiple CVEs at once:
curl "https://api.first.org/data/v1/epss?cve=CVE-2021-44228,CVE-2023-22515"
# Top 100 CVEs by EPSS score (!epss = descending order):
curl "https://api.first.org/data/v1/epss?order=!epss&limit;=100"
# CVEs with EPSS > 0.5 (50%+ probability of exploitation):
curl "https://api.first.org/data/v1/epss?epss-gt=0.5"
# Retrieve historical score:
curl "https://api.first.org/data/v1/epss?cve=CVE-2021-44228&date;=2021-12-15"
Integration in Python:
import requests
def get_epss(cve_id: str) -> dict:
r = requests.get(
f"https://api.first.org/data/v1/epss?cve={cve_id}"
)
data = r.json()["data"]
if data:
return {
"cve": cve_id,
"epss": float(data[0]["epss"]),
"percentile": float(data[0]["percentile"])
}
return {"cve": cve_id, "epss": 0.0, "percentile": 0.0}
# Enrich vulnerability scan output:
vulnerabilities = [
{"cve": "CVE-2021-44228", "cvss": 10.0},
{"cve": "CVE-2023-1234", "cvss": 7.5},
]
for vuln in vulnerabilities:
epss_data = get_epss(vuln["cve"])
vuln["epss"] = epss_data["epss"]
vuln["priority"] = vuln["cvss"] * (1 + epss_data["epss"]) # Combined score
# Sort by combined score:
sorted_vulns = sorted(vulnerabilities, key=lambda x: x["priority"], reverse=True)
SIEM Integration (Sentinel KQL):
SecurityAlert
| where AlertName contains "CVE"
| extend cve_id = extract("CVE-[0-9]+-[0-9]+", 0, AlertName)
| externaldata (cve: string, epss: real)
[@"https://api.first.org/data/v1/epss"] with (format="json")
| lookup (SecurityCVEs | where epss > 0.5) on cve_id
| where isnotnull(epss)
| order by epss desc
EPSS in Practice
Tenable.io EPSS Integration:
- Since 2023: EPSS score directly in the Tenable UI
- Filter: "Show only CVEs with EPSS > 0.50"
- VPR (Vulnerability Priority Rating): combines CVSS + EPSS + asset context
Qualys TruRisk:
- ""Exploit Maturity" is based on EPSS and KEV
- QDS (Qualys Detection Score): Combines CVSS + EPSS + KEV
Rapid7 InsightVM:
- "Real Risk Score": Integrates EPSS
- Dashboard: "Top Remediation" based on EPSS + accessibility
CISA KEV + EPSS = Gold Standard
KEV (Known Exploited Vulnerabilities) is the list of CVEs that CISA has confirmed are actively exploited ("Confirmed exploitation in the wild") – mandatory patch for U.S. government agencies.
| Combination | Recommendation |
|---|---|
| KEV-listed + EPSS > 0.5 | IMMEDIATELY (patch today!) |
| KEV-listed + EPSS < 0.5 | Within 24 hours (KEV is mandatory!) |
| EPSS > 0.5 (no KEV) | Within 7 days |
| EPSS 0.1–0.5 | Normal patch cycle (30 days) |
| EPSS < 0.1 | Prioritize based on severity |
# Download CISA KEV:
curl https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json \
| jq '.vulnerabilities[] | {cveID, product, dateAdded}'
EPSS Limitations:
- No context: EPSS does not know if your system is exposed
- Latency: new CVEs take days before EPSS data is available
- No zero-day: unknown CVEs have no EPSS score
- No business impact: a $100k system and a test system are treated the same
- Solution: EPSS + asset context + business impact = complete prioritization