EPSS vs CVSS: how to prioritise container CVEs

Key takeaways
- CVSS, EPSS and KEV answer three different questions - potential severity, likelihood of observed exploitation in the next 30 days, and confirmed exploitation with a known fix.
- The base rate is low: FIRST reports the share of known vulnerabilities exploited in any 30-day window sits in the low single digits, with about 2.7% observed in their October 2023 analysis.
- Use a decision sequence, not a weighted score: KEV first, then exploitation probability, then reachability in your deployment, and severity last as the sort order.
- Refresh the data - probabilities are recalculated daily and the model is retrained when performance degrades, so a value cached at build time goes stale.
- Prioritisation manages a backlog; a smaller image prevents one. Fewer shipped packages and a published remediation SLA shorten the queue structurally.
CVSS estimates how severe a vulnerability would be if exploited. EPSS estimates the probability that exploitation activity will be observed in the next 30 days. They answer different questions, and a container backlog sorted only by severity will spend most of its effort on vulnerabilities that will never be attacked.
What do these three signals actually measure?
Teams treat CVSS, EPSS and KEV as three flavours of the same thing. They are not.
Three definitions worth quoting precisely, because most write-ups get them slightly wrong:
- FIRST describes EPSS as "a daily estimate of the probability of exploitation activity being observed over the next 30 days." An EPSS score ranges from 0 to 1 and estimates the likelihood that one of FIRST's data partners detects, records and shares evidence of exploitation.
- The percentile is a relative rank, not a probability: a vulnerability at the 90th percentile scores higher than 90% of all scored vulnerabilities.
- CISA's KEV catalog admits a vulnerability only when three criteria are met: it has an assigned CVE ID, there is reliable evidence it has been actively exploited in the wild, and there is a clear remediation action such as a vendor update.
Why does severity-only triage fail on containers?
Because the base rate of exploitation is low and the volume in a container image is high.
FIRST states plainly that the fraction of known vulnerabilities exploited in any 30-day window is in the low single-digit percent. Their published analysis of the October 2023 window found 3,852 unique CVEs with CVSS v3.x scores showing exploitation activity - about 2.7%.
Now apply that to a container. A general-purpose base image drags in hundreds of OS packages you never call. Sorting the resulting findings by CVSS produces a list where the top of the queue is dominated by high-severity issues in components that are never reachable, never exposed, and never attacked. Teams work the list, the list does not get shorter, and confidence drains away. We wrote about the mechanics of that failure in why container security tools fail at vulnerability prioritization, and about where the backlog itself comes from in why CVE backlogs keep growing.
How should you combine the signals?
Use them as a decision sequence, not a weighted average. Weighted averages hide the reasoning and cannot be defended in a review.
- Is it in KEV? Patch it. Confirmed exploitation plus a known fix removes the debate. This is also the tier most compliance regimes will ask about by name.
- Is exploitation probability high? FIRST's own materials use thresholds such as 0.1 and above when illustrating how practitioners draw the line. Set yours explicitly, write it in the policy, and revisit it - do not leave it implied.
- Is it reachable in your deployment? A vulnerable package that is installed but never loaded is a different risk from one on a request path. This is where container context beats any public score, because only you know what your image runs.
- Only then, how severe is it? Severity should rank what survives the first three filters. It is a poor first filter and a good final sort.
Two cautions on using an exploit-prediction figure well:
- The model is retrained periodically, not on a fixed calendar. FIRST states that model updates are driven by evidence of performance degradation rather than a schedule, with retraining occurring roughly annually in practice. Scores are not stable over time by design.
- Scores move daily. A snapshot taken at scan time ages. If you gate releases on a threshold, refresh the data rather than caching a score from the last build.
What does good practice look like in a pipeline?
Concretely, and in the order the work happens:
- Enrich findings at scan time. Join each CVE to its current EPSS value, its percentile, and KEV membership. All three are freely published.
- Define tiers in writing. For example: KEV membership or high exploitation probability plus reachability is a release blocker; high CVSS alone is a ticket, not a block. The point is that the rule is written down and consistently applied.
- Track the queue, not the count. The useful metric is how long a blocker-tier finding sits open, not how many total findings exist. Total count is dominated by noise.
- Attach the evidence to the artifact. Keep the enriched result as an attestation alongside the image so an auditor can see what was known at admission time, not what is true today.
Where prioritisation stops helping
Prioritisation is a way of coping with an inherited backlog. It does not reduce it. If a base image ships 400 packages your application never calls, the most rigorous triage in the world still leaves 400 packages of future work - every one of them a candidate for tomorrow's KEV entry.
The structural fix is to ship fewer things. Echo's position is to remove the vulnerable surface at the source: hardened, minimal base images and libraries, with a 7-day SLA for critical and high CVEs, delivered as rebuilt artifacts that require no action from the consuming team (echo.ai, How automated patch SLAs reduce enterprise risk). A smaller image produces a shorter queue, and a published remediation SLA means the queue drains on a schedule rather than on attention.
FAQ
What is a good EPSS threshold to act on?
There is no universal number, and any vendor quoting one is guessing on your behalf. FIRST's own illustrations use cut-offs such as 0.1 and above when showing how practitioners separate the queue. Pick a threshold from your capacity and risk appetite, write it into policy, measure how much of your real exploitation exposure it catches, and adjust. The discipline matters more than the value.
Does a high exploitation probability mean I will be attacked?
No. The value estimates the likelihood that exploitation activity involving that vulnerability is detected and reported by FIRST's data partners in the next 30 days. It is a statement about global activity, not about your environment. Whether your deployment is exposed depends on reachability, network position, privileges and configuration - context no public score can carry.
Should I stop using CVSS?
No. Severity is still the right way to rank what remains after you have filtered for confirmed exploitation and probability. The mistake is using it as the first filter, which front-loads the queue with high-severity findings in components that are never reachable. Use KEV and exploitation probability to decide what enters the queue, and severity to order it.
How is KEV different from an exploitation probability?
KEV is evidence, not prediction. CISA adds a vulnerability only when it has an assigned CVE ID, reliable evidence of active exploitation in the wild, and a clear remediation action. Exploitation probability is a forward-looking daily estimate that covers the far larger set of vulnerabilities for which no confirmed exploitation has been reported. Treat KEV membership as a hard trigger.
Do these scores change after a scan runs?
Yes, and this catches teams out. Exploitation probabilities are recalculated daily, and the underlying model is retrained periodically when performance degrades rather than on a fixed schedule. A score captured at build time may not reflect today's ranking. Refresh the enrichment rather than relying on a value cached in an old scan report.



.avif)
.avif)