Published 2026-04-29 · 10 min read

EPSS explained — when CVSS isn't enough

You have 800 CVE findings on your homelab and one evening to patch the urgent ones. CVSS gives you a severity score, but severity ≠ urgency. EPSS — the Exploit Prediction Scoring System — is the missing dimension: a 0–1 probability of actual exploitation in the next 30 days. Combined with CVSS, it cuts triage time by an order of magnitude.

The triage problem CVSS doesn't solve

CVSS scores answer "how bad is this if exploited?" — a structural question about the vulnerability's properties (network-attackable, no auth required, results in code execution). It says nothing about whether anyone is *likely* to exploit it.

That gap is enormous in practice. A typical Linux host has 40+ open CVEs at any given moment with CVSS ≥ 7.0; treating all of them as same-day patch priorities turns operators into patch-fatigued cynics who eventually ignore the dashboard. Most of those 40 CVEs will never be exploited against any target, ever. A handful will. Knowing which is the difference between "I patched the right thing tonight" and "I burned Saturday on something that didn't matter."

What EPSS is

The Exploit Prediction Scoring System is a model maintained by FIRST.org (the same body behind CVSS). For every published CVE, EPSS produces:

Scores are recomputed daily on the full CVE corpus. The model is an XGBoost ensemble trained on ~30 features per CVE, including:

The model is public and the EPSS project page publishes the daily-recomputed scores as open data. Every major commercial vulnerability scanner pulls from the same source.

How to read an EPSS score

EPSS values are not evenly distributed — most CVEs have very low scores, and a long tail has high ones. Rough buckets:

EPSSReadingAction
< 0.01~95% of all CVEs land here. The model's prediction is "essentially nobody will exploit this within a month."Patch in your normal cycle. Don't lose sleep.
0.01 – 0.10Some attention from public researchers; PoCs may exist; not yet seen in the wild.Worth a same-week patch on internet-facing services. Backlog-worthy on internal-only.
0.10 – 0.50Active interest. PoCs almost certainly exist; mass-scanner inclusion may be days away.Same-day on internet-facing. Same-week on internal.
> 0.50Very likely to be exploited soon if not already. Combined with KEV inclusion, this means right now.Patch tonight on internet-facing. Patch this week on internal.

A heuristic: a CVE with EPSS > 0.10 deserves attention regardless of its CVSS. The model is saying "this thing is moving" — high CVSS or low, that's a reason to look.

The big counter-intuitive case: high CVSS, low EPSS

Most CVEs in your scan results will have CVSS 7.0+ (the bulk of "high" and "critical" buckets) but EPSS < 0.05. That pattern is the model saying: "yes, this would be bad if exploited, but it almost certainly won't be exploited in the next month." Reasons that's a true signal:

A CVSS 9.8 with EPSS 0.001 is an order of magnitude less urgent than a CVSS 7.5 with EPSS 0.40. The triage decision tree should reflect that.

EPSS vs KEV — they answer different questions

CISA's Known Exploited Vulnerabilities (KEV) catalogue is a curated list of CVEs that have *confirmed* exploitation in the wild. EPSS is a *predictive* model — "likely to be exploited" — versus KEV's *confirmed* observation — "we have receipts."

The two complement each other:

Both signals are public data; both should appear on every CVE finding in a serious vulnerability scanner.

Where EPSS falls short

Three known limitations worth knowing about:

Lagging indicator on novel attack patterns

EPSS learns from past exploitation patterns. Genuinely novel attack types — a new CWE class, a new privilege escalation gadget — will score low until enough public signal accumulates. The model is a rear-view mirror with predictive smoothing, not a crystal ball.

Targeted attacks don't show up

EPSS scores reflect *mass* exploitation patterns. A nation-state actor sitting on a 0-day for six months while attacking three specific organisations will not move the EPSS score on that CVE — until the 0-day is publicly disclosed and mass scanners start using it. If your homelab is in someone's specific crosshairs (unlikely, but possible — journalists, activists, researchers, founders of payment-processing companies), EPSS is not the right signal to triage by.

Your environment isn't the average

EPSS scores reflect what attackers do globally. Your *exposure* to a given CVE depends on your environment — is that vulnerable service internet-facing, behind a VPN, or LAN-only? A CVE with EPSS 0.6 on a service you don't expose is less urgent than one with EPSS 0.3 on your edge proxy. Use EPSS as one input, not the whole answer.

A worked example

A scan finds three CVEs on your homelab edge box:

CVECVSS v3EPSSKEV?Service
CVE-A9.80.002NoAn internal-only metrics dashboard
CVE-B7.50.42NoYour reverse proxy (public)
CVE-C8.10.94YesSSH (public)

The naive CVSS-only ordering: A (9.8) → C (8.1) → B (7.5).

The EPSS-aware ordering: C (KEV + 0.94 + public) tonight; B (0.42 + public) this week; A (0.002 + internal-only) next cycle. The 9.8 CVSS that scared the audit software is the lowest urgency of the three; the 8.1 that sits below it on a CVSS-only list is the actually urgent one.

That re-ordering is *the* triage win EPSS gives you. It's not a replacement for CVSS; it's the second axis that makes a flat severity list into a real action plan.

How Noxen surfaces EPSS

Every CVE finding in Noxen carries the upstream EPSS score and KEV-listed flag when the upstream feed includes them. Findings > 0.10 EPSS show as a yellow tag on the row; KEV-listed findings show as a green "KEV" badge regardless of CVSS. The dashboard's default sort is severity-first; toggle to EPSS-weighted to see findings ordered by the "how likely is this actually exploited" axis described above.

The severity-scoring docs cover the precedence rules (distro-tagged severity → CVSS v3 → database fallback) — KEV/EPSS overlay tags on top of those buckets, they don't replace them. Noxen never re-scores upstream data; the EPSS values you see come straight from FIRST.org's daily publication via the signed CVE feed.

The TL;DR