Vulnerability Management

EPSS vs CVSS for Vulnerability Prioritization: Using Both Without Double-Counting

Ethan Park · · 8 min read
Abstract visualization of two scoring signals converging into a single prioritization vector

Here's a situation we ran into repeatedly before we built Vendrsec: a CVE with a CVSS base score of 9.1 and an EPSS score of 0.0012. Both numbers are accurate. The CVSS score reflects a remotely exploitable, low-complexity vulnerability with high impact across confidentiality, integrity, and availability. The EPSS score says there's roughly a 0.12% probability it gets exploited in the wild in the next 30 days. Which one do you believe?

The answer — frustratingly — is both, and that's the actual challenge. CVSS and EPSS measure genuinely different things. Using either one in isolation leaves a meaningful blind spot. Using both naively creates a different problem: if you multiply or weight them together without understanding what each number represents, you're double-counting assumptions that are already baked into each model.

This post is about what EPSS actually predicts, where it complements CVSS rather than duplicating it, and how we think about combining the two into a prioritization signal that's stronger than either alone.

What EPSS Actually Predicts

EPSS — the Exploit Prediction Scoring System maintained by FIRST — outputs a probability between 0 and 1 representing the likelihood a given CVE will be exploited in the wild within the next 30 days. The model is trained on observed exploitation evidence from a consortium of sources: honeypot telemetry, IDS/IPS signature triggers, threat intelligence feeds, and NVD metadata.

That 30-day window is worth internalizing. EPSS doesn't tell you whether a CVE is theoretically exploitable, or how severe the impact would be if exploited. It tells you, based on current threat actor behavior and available tooling, how likely something is to be actively attacked in the near term. A CVE that has been public for three years with no exploitation activity will have a low EPSS score even if its CVSS base score is 9.8. A recently disclosed CVE where a public exploit appeared on GitHub within 48 hours of disclosure will climb quickly.

EPSS scores are also dynamic — they're updated daily. A CVE that had an EPSS score of 0.003 last month may have moved to 0.41 if a PoC was published, if it was added to CISA's Known Exploited Vulnerabilities catalog, or if active exploitation was observed in honeypot data. This means your EPSS-augmented prioritization list isn't static and shouldn't be treated as such.

What CVSS Measures (and What It Doesn't)

CVSS 3.1 and CVSS 4.0 base scores measure inherent characteristics of a vulnerability: attack vector, attack complexity, privileges required, user interaction, and potential impact on confidentiality, integrity, and availability. These are properties of the vulnerability itself, scored independently of any deployment context and independently of whether anyone is actually trying to exploit it.

The base score doesn't know anything about your environment. It doesn't know whether the affected service is internet-facing or air-gapped. It doesn't account for compensating controls — a WAF rule, a network segmentation boundary, an EDR rule that detects the exploit behavior. It doesn't change based on whether active exploit tooling exists.

CVSS 3.1 temporal metrics were designed to address the exploit availability question — they include an "Exploit Code Maturity" modifier. In practice, these temporal scores are rarely populated in NVD data, and the maturity classification (Proof-of-Concept / Functional / High) is coarser than what EPSS provides.

The key distinction: CVSS describes the vulnerability. EPSS describes current threat actor interest in that vulnerability. They're orthogonal dimensions.

The Double-Counting Trap

The naive approach to combining EPSS and CVSS is to multiply them or average them. The problem is that certain CVSS dimensions correlate with exploitation likelihood in ways that are already reflected in the EPSS model.

Consider attack vector. A vulnerability with AV:Network and AV:Local have very different realistic exploitation profiles. Network-accessible vulnerabilities attract more exploitation attempts simply because more attackers can reach them remotely. The EPSS model has already absorbed this — network-accessible CVEs with public PoC exploits dominate the high-EPSS population. If you also weight your combined score by CVSS attack vector, you're effectively penalizing local-access vulnerabilities twice (once in CVSS, once implicitly through EPSS).

Similarly, CVSS attack complexity correlates inversely with exploitation rate. Low-complexity vulnerabilities — ones that require no special conditions to exploit — appear disproportionately in the high-EPSS tier because they're easier to weaponize. If you multiply CVSS base score (which includes attack complexity) by EPSS directly, you're double-weighting complexity.

The less error-prone approach is to use CVSS for impact assessment and EPSS for threat likelihood, keeping them as separate inputs rather than collapsing them into a single multiplication. Your prioritization signal then has a form like: prioritize based on impact potential (CVSS environmental score adjusted for asset criticality) when threat likelihood (EPSS) exceeds a threshold, not by multiplying the two together.

A Practical Tiering Framework

We work with a 2x2 grid: EPSS threshold (high vs. low) on one axis, CVSS environmental score (high vs. low) on the other. The environmental score incorporates base score plus your modifications for asset criticality and compensating controls — not the raw base score from NVD.

High EPSS + high environmental CVSS: remediate immediately. These are the findings where threat actors are actively interested AND the impact to your specific environment would be significant. This is a small bucket — typically under 5% of your total finding volume — and it should be your sprint-blocking tier.

High EPSS + low environmental CVSS: investigate quickly, but don't sprint-block. Active exploitation exists but your exposure or impact is limited. Check whether compensating controls are actually effective (not just assumed), then move to a defined SLA — a week or two, not "someday."

Low EPSS + high environmental CVSS: this is the theoretically dangerous, currently quiet category. Don't deprioritize it entirely — these are the CVEs that can move from 0.003 to 0.4 EPSS in a week if a PoC drops. Set a longer SLA but watch the EPSS trend. We alert when any finding in this cell crosses an EPSS threshold.

Low EPSS + low environmental CVSS: schedule-based patching, standard cadence. No sprint interruption justified.

CISA KEV as a Third Signal

CISA's Known Exploited Vulnerabilities catalog is worth treating as its own input rather than folding it into EPSS. A KEV listing means CISA has confirmed active exploitation, which is stronger evidence than EPSS's probabilistic model — KEV is ground truth, not a forecast. EPSS should correlate with KEV entries but doesn't always lead them.

In practice, most KEV entries already have high EPSS scores by the time they're listed. But occasionally a CVE gets added to KEV while its EPSS is still updating — there's a lag in the threat data pipeline that feeds the EPSS model. If you're relying solely on EPSS, you can miss a short window where active exploitation is confirmed but the score hasn't moved yet.

Our approach: KEV membership overrides EPSS scoring in triage. If a finding is in KEV and affects assets in your inventory, it moves to the highest remediation tier regardless of the current EPSS percentile. The KEV catalog is conservatively maintained — CISA doesn't add CVEs speculatively — so a KEV hit is a hard signal.

Where This Falls Short

We're not saying EPSS is a complete exploitation predictor. The model reflects what has been exploited, weighted toward exploitation patterns that generate observable signals (honeypot hits, IDS signatures). Zero-day exploitation by nation-state actors may not be captured until after disclosure. Highly targeted exploitation against specific sectors or geographies may generate limited honeypot data and therefore lower EPSS scores than the actual threat level warrants.

EPSS also doesn't account for your specific threat model. If you're running OT systems in a manufacturing environment, your adversary profile is different from a SaaS company's. The EPSS model reflects the aggregate threat landscape, not your slice of it. For organizations with well-defined adversary profiles — threat intelligence teams have mapped specific APT groups to their sector — EPSS should be one input among several, not the definitive likelihood signal.

What EPSS does well: it reliably identifies the CVEs that commodity attackers are actively weaponizing. For most security teams dealing with a general threat landscape and more findings than they can possibly remediate, that's the most useful signal available. The top 1% of CVEs by EPSS score represent a disproportionate share of observed exploitation. If you're not starting there, you're starting somewhere less useful.

The goal is not a perfect model — it's a signal that's better than sorting by CVSS base score alone, which has been the default in most vulnerability management programs since CVSS was introduced. EPSS + CVSS environmental score, kept as separate dimensions rather than collapsed into a single number, gets you materially closer to working on the right things first.

See these principles in action