DEV Community

Rushabh Shah
Rushabh Shah

Posted on Originally published at depwarden.in

CVSS, EPSS and KEV: how to actually prioritize dependency vulnerabilities

Every week a dependency scanner finds dozens of vulnerabilities. Every week most developers ignore them, because there's no time to fix 200 issues and no obvious way to know which 3 actually matter. The answer lives in three numbers: CVSS, EPSS and KEV. Understanding what each one measures — and what it doesn't — is the difference between a security backlog that never shrinks and one you can actually work through.

CVSS: severity, not risk

The Common Vulnerability Scoring System (CVSS) gives every published CVE a score from 0 to 10 based on how bad the vulnerability could be in a worst-case scenario. CVSS 9.8 sounds terrifying. The problem is that CVSS scores are entirely theoretical — they describe the vulnerability in the abstract, with no reference to how often it's actually exploited or whether attackers even care about it.

In practice, fewer than 5% of published CVEs are ever exploited in the wild. A CVSS 9.8 in a library feature you don't use, in an attack path that requires local access you don't expose, is a lower priority than a CVSS 6.0 that's actively being used in ransomware campaigns. Sorting by CVSS alone means you're sorting by worst-case theory, not real-world risk.

That's why CVSS is the starting point, not the answer.

EPSS: exploitation probability

The Exploit Prediction Scoring System (EPSS), maintained by FIRST, takes a very different approach. It's a machine-learning model trained on actual exploitation evidence — threat intelligence feeds, honeypot data, proof-of-concept exploit activity, CISA data and more. It produces a daily probability score (0–1) for the likelihood that a given CVE will be exploited in the next 30 days.

The numbers are striking: the top 1% of CVEs by EPSS account for roughly 75% of observed exploitation attempts. The bottom 80% have near-zero probability of being exploited. This means if you filter to CVEs with EPSS > 0.10 (10% probability), your fix list shrinks dramatically while still covering the overwhelming majority of real attacks.

EPSS is updated every day as new exploitation evidence arrives, so a CVE that was low-priority last month can jump to high-priority overnight if attackers start weaponizing it.

KEV: confirmed exploitation in the wild

The CISA Known Exploited Vulnerabilities (KEV) catalog is the most reliable signal of all. CISA — the U.S. Cybersecurity and Infrastructure Security Agency — maintains a manually curated list of vulnerabilities that have been confirmed exploited in real-world attacks. These aren't predictions; they're facts. If a CVE is in the KEV catalog, attackers have working exploits and are actively using them.

The KEV list is legally binding for U.S. federal agencies (CISA mandates remediation within 2–3 weeks) but is freely published for everyone. KEV entries often have EPSS scores near 1.0, but not always — a CVE targeting industrial control systems might be KEV-listed with a lower EPSS simply because the affected population is small.

KEV findings are always your highest priority, regardless of CVSS.

A worked example

Suppose a scan of a mid-sized Node.js service returns five open findings. Here's what a naive CVSS-only sort produces versus what the KEV/EPSS-aware ranking produces:

Finding CVSS EPSS (illustrative) KEV Fix available
A — RCE in a logging library, reachable from a public HTTP handler 9.8 0.94 Yes Yes
B — Deserialization bug in an admin-only internal tool 9.1 0.02 No Yes
C — Prototype pollution in a deep transitive utility package 7.5 0.03 No Yes
D — SSRF in a webhook-delivery library, actively targeted this quarter 6.5 0.61 No Yes
E — Denial-of-service in a rarely-used parsing edge case 5.3 0.01 No No

Sorted by CVSS alone, the order is A, B, C, D, E — B (9.1) outranks D (6.5) despite D being far more likely to actually be exploited.

Sorted by KEV, then EPSS, then CVSS, the order becomes:

  1. A — KEV-listed and the highest EPSS in the set. Fix this week, full stop.
  2. D — not KEV-listed, but EPSS of 0.61 puts it in the top slice of real-world exploitation activity. Fix in the current sprint, ahead of B.
  3. B — high CVSS, but an EPSS of 0.02 says almost nobody is actually exploiting it (consistent with it requiring admin access an external attacker doesn't have). Schedule normally.
  4. C — same story as B: real bug, low real-world pressure. A fix exists, so bundle it into the next routine dependency bump rather than an emergency patch.
  5. E — lowest EPSS, no fix available yet, and the weakest CVSS in the set. Accept and monitor; revisit if a fix ships or its EPSS moves.

The CVSS-only ranking would have burned a week fixing B before D — the finding attackers were actually using. This is the entire value of layering EPSS and KEV on top of CVSS: it's not that CVSS is wrong, it's that CVSS alone answers "how bad could this be," not "should I fix this today."

Putting them together: a practical priority order

A useful mental model:

  1. KEV-listed + fix available → fix immediately, this week.
  2. EPSS > 0.20 + fix available → fix in the current sprint.
  3. CVSS Critical + EPSS < 0.05 → schedule, deprioritise over items 1–2.
  4. CVSS Medium with no fix → accept/document, monitor.
  5. Everything else → triage periodically, don't block releases.

Two more signals matter beyond these scores:

  • Direct vs transitive — a vulnerability in a package you import directly is a higher priority than the same CVE in a package five levels deep that you can't easily upgrade.
  • Fix availability — upgrading to a safe version is a different problem than waiting for the upstream to patch. If there's no fix, your option is mitigation or accepting the risk, not just "upgrade".

If your organisation needs a documented SLA (for a customer contract, an audit, or an internal policy), it's reasonable to turn this into fixed remediation windows: KEV-listed findings within 7 days (matching CISA's own federal mandate as a sane external benchmark), EPSS above 0.20 within 30 days, everything else on your normal release cadence. Write the policy in terms of KEV/EPSS thresholds rather than a flat CVSS cutoff — a CVSS-only SLA ("fix all Criticals within 30 days") is exactly the policy that produces the wasted-effort scenario in the worked example above.

Common mistakes teams make with these three signals

Treating CVSS as a risk score. CVSS measures theoretical severity, not likelihood. A team that gates CI purely on "no CVSS >= 7" will spend real engineering time on findings nobody is exploiting while a lower-CVSS, high-EPSS finding sits unpatched in the same backlog. Use CVSS to understand impact, and EPSS/KEV to understand urgency — they answer different questions and neither replaces the other.

Ignoring EPSS because it "isn't a real number." EPSS is a probability, not a certainty, and it does move — a score of 0.02 today can become 0.80 within days of a public proof-of-concept exploit landing. Teams that check EPSS once and never again lose exactly the signal that makes it useful. It's designed to be re-checked, not memorised.

Forgetting that KEV is a floor, not a ceiling. A vulnerability leaving the KEV catalog (CISA does periodically review and remove stale entries) doesn't mean it's safe — it means active campaigns have moved on. A vulnerability entering KEV, on the other hand, should immediately jump every other prioritisation signal you're using, including a low EPSS score computed before the exploitation started.

Sorting the whole backlog instead of triaging the top slice. You don't need a perfect ranking of 200 findings. You need a reliable way to identify the 5-10 that matter this week. Spending analyst time perfectly ordering findings 50 through 200 is wasted effort next to just clearing the KEV-listed and high-EPSS findings first and re-triaging weekly.

Where to get EPSS and KEV data yourself

Both are free and public, with no API key required for reasonable use. EPSS scores are published daily by FIRST at api.first.org/data/v1/epss — query by CVE ID and get back the current probability plus a percentile rank. CISA KEV is a single JSON file at cisa.gov's known-exploited-vulnerabilities feed, updated as CISA confirms new active exploitation; there's no per-CVE lookup API, so most tooling downloads and caches the full catalog. Combined with CVSS from NVD or the CVE's own CNA record, this is enough to build the priority order above by hand — or a scanner can fetch and merge all three automatically, which is what removes the manual step.

What DepWarden does with this

DepWarden fetches EPSS scores and KEV status daily from their respective sources alongside the OSV vulnerability mirror. In the scan results, KEV findings are called out first with a red flag, EPSS scores are shown alongside CVSS so you can compare them at a glance, and the "Fix these first" ranking uses a composite of these signals — not a raw CVSS sort — to produce a list ordered by real-world risk. The goal is to put the three actionable fixes at the top, not the eighty theoretical ones.

Top comments (0)