Vulnerability prioritization: how to combine CVSS, EPSS, CISA KEV and runtime context instead of drowning in CVEs
Why scanners produce endless CVE lists, what CVSS and EPSS really measure, how the CISA KEV catalog helps and how runtime context from observability turns thousands of findings into a short, owned work queue.
Summary
- CVSS describes how severe a vulnerability is in general, EPSS estimates how likely it is to be exploited in the next 30 days, and the CISA KEV catalog lists vulnerabilities with reliable evidence of exploitation in the wild.
- None of these signals knows your environment: runtime context such as whether a library is loaded, reachable, internet-exposed and handling sensitive data decides what is actually urgent.
- A simple priority model with owners, example SLAs and two metrics, mean time to remediate per priority and open known-exploited CVEs, turns a CVE flood into a measurable process.
Vulnerability prioritization is the discipline of deciding which of the many known vulnerabilities in your software you fix first, and which can wait. Most teams do not lack findings: a single container image scan can return hundreds of CVEs, and a fleet of services quickly produces thousands. What they lack is a defensible way to say "these twenty matter this week" and to prove afterwards that the decision was right.
This guide explains why scanners produce such long lists, what CVSS and EPSS actually measure (and what they do not), how the CISA Known Exploited Vulnerabilities catalog fits in and why runtime context from observability is the missing ingredient. It ends with a priority model you can adapt, example SLAs, metrics for measuring progress and a copyable triage checklist.
Why scanners produce endless CVE lists
Software composition analysis and container scanners work by inventory: they read package manifests, lock files and image layers, match every component and version against vulnerability databases and report every match. That approach is thorough by design, and it explains the volume:
- Transitive dependencies: a service with a few dozen direct dependencies often pulls in hundreds of indirect ones. Each of them can carry its own CVEs.
- Base images: operating system packages in a base image are reported even if your application never calls them.
- Duplicates across services: the same vulnerable library in forty services shows up as forty findings, although it is one decision.
- No runtime knowledge: a scanner sees what is installed, not what is loaded, executed, reachable from the network or handling customer data.
The result is a list sorted by severity score, in which a large share of "critical" findings sits in code that never runs in production. Teams that try to fix everything burn out; teams that ignore the list miss the few findings that attackers actually use. The answer is to combine several signals, each of which answers a different question.
CVSS: what the base score means and what it does not
The Common Vulnerability Scoring System (CVSS) is maintained by FIRST, the Forum of Incident Response and Security Teams. The current version, CVSS v4.0, was published on November 1, 2023. According to the specification, CVSS produces numerical scores that indicate the severity of a vulnerability relative to other vulnerabilities. Version 4.0 organizes metrics into four groups:
- Base: intrinsic characteristics of the vulnerability that are constant over time and across user environments, such as attack vector, attack complexity, the new attack requirements metric, privileges required and impact.
- Threat: characteristics that change over time, such as the maturity of exploit code (this group replaces the former temporal metrics).
- Environmental: characteristics specific to your environment, such as security requirements and modified base metrics.
- Supplemental: additional context that, per the specification, does not modify the final score.
CVSS v4.0 also introduced nomenclature that makes clear which groups went into a score: CVSS-B (Base only), CVSS-BT (Base and Threat), CVSS-BE (Base and Environmental) and CVSS-BTE (all three). The qualitative rating scale maps scores to None (0.0), Low (0.1–3.9), Medium (4.0–6.9), High (7.0–8.9) and Critical (9.0–10.0).
Key point: almost every scanner shows a CVSS-B score, the Base score. It describes how bad a vulnerability could be in a generic environment. It does not tell you whether anyone is exploiting it, whether the vulnerable code runs in your system or what the business impact would be. FIRST itself stresses that CVSS is not just the Base score.
Use the Base score to understand potential impact, not as a to-do list order. Sorting thousands of findings by Base score alone puts many "9.8" findings in unused code ahead of a "7.5" that is actively exploited on your internet-facing login service.
EPSS: the probability of exploitation
The Exploit Prediction Scoring System (EPSS), also maintained by FIRST, answers a different question: how likely is it that a published CVE will be exploited in the wild in the next 30 days? EPSS is a data-driven machine-learning model that publishes a probability between 0 and 1 for every CVE every day, along with a percentile that ranks a vulnerability against all currently scored vulnerabilities. The model has been revised several times; FIRST lists EPSS v4 (model v2025.03.14) as publishing from March 17, 2025, and EPSS v5 (model v2026.06.15) as publishing from June 15, 2026. Each version shifted scores on its start date.
Three things are important when using EPSS:
- Probability, not severity: an EPSS score of 0.4 means an estimated 40 % probability that exploitation activity is observed within 30 days. A high CVSS and a low EPSS score can both be accurate, because they measure different things.
- Do not multiply CVSS by EPSS: the EPSS FAQ explicitly says that multiplying the two does not compute probability times severity and is never a good idea. Use them as separate dimensions.
- No environment knowledge: EPSS does not account for compensating controls or your architecture. FIRST suggests combining it with presence, reachability and consequence, which is exactly where runtime context comes in.
CISA KEV: evidence of exploitation in the wild
The Known Exploited Vulnerabilities (KEV) catalog of the US Cybersecurity and Infrastructure Security Agency (CISA) is described by CISA as the authoritative source of vulnerabilities that have been exploited in the wild. A vulnerability is added only if it meets three criteria: it has an assigned CVE ID, there is reliable evidence that it has been actively exploited, and there is a clear remediation action such as a vendor update. Scanning, security research or proof-of-concept code alone do not count as active exploitation.
US federal civilian agencies are required by binding operational directive to remediate KEV entries within prescribed timeframes (the criteria originate in BOD 22-01 and are carried forward by BOD 26-04). Other organizations are not bound, but CISA strongly recommends that all stakeholders include a requirement to address KEV vulnerabilities immediately in their vulnerability management plans. For a prioritization model, KEV is the strongest single "urgent" signal: it reflects observed attacks rather than a prediction.
Runtime context: the signal scanners cannot see
CVSS, EPSS and KEV describe the vulnerability. Runtime context describes your exposure to it. This is the information observability data already holds, because traces, metrics, logs and the service topology show what really runs and talks to what:
- Is the vulnerable library loaded? A package in an image that no running process loads is far less urgent than one in the active class path.
- Is the vulnerable code path reachable? If traces show that the affected function or endpoint is executed, exploitation becomes realistic.
- Is the service internet-exposed? Topology and ingress data show whether a service receives traffic from outside or sits several hops behind internal services.
- Does it process sensitive data? Personal data, payment data or credentials raise the business impact of a compromise.
- Who owns it? A finding without an owner is never fixed. A service catalog with owning teams and on-call rotations turns findings into assigned work.
Signals at a glance
| Signal | What it tells you | Source |
|---|---|---|
| CVSS Base score (CVSS-B) | Generic technical severity if exploited | FIRST specification; scores from NVD, vendors or scanners |
| CVSS Threat/Environmental (CVSS-BT, -BE, -BTE) | Severity adjusted for exploit maturity and your environment | Your own assessment using the FIRST calculator |
| EPSS probability and percentile | Likelihood of exploitation activity in the next 30 days | FIRST EPSS data feed and API, updated daily |
| CISA KEV listing | Reliable evidence of active exploitation in the wild | CISA KEV catalog (CSV/JSON) |
| Library loaded at runtime | Whether the vulnerable component actually runs | Runtime agent, process and class-loading data |
| Code path reachable | Whether the affected function or endpoint is executed | Distributed traces, profiling data |
| Internet exposure | Whether attackers can reach the service directly | Service topology, ingress and load balancer data |
| Sensitive data | Business and regulatory impact of a compromise | Data classification, service catalog metadata |
| Owner | Who fixes it and who is accountable | Service catalog, code ownership |
A prioritization model that combines the signals
Avoid a single magic formula. A small decision table is easier to explain to auditors and engineers and easier to tune. The model below is an example to adapt; thresholds such as the EPSS cut-off depend on your capacity and risk appetite.
| Priority | Example rule |
|---|---|
| P1 – fix now | Listed in CISA KEV and loaded at runtime and internet-exposed or handling sensitive data |
| P2 – fix this sprint | KEV-listed but internal only, or high EPSS (example: top percentiles you define) and reachable, or CVSS Critical, reachable and exposed |
| P3 – planned | Loaded at runtime but not reachable or not exposed, no KEV listing, low EPSS |
| P4 – backlog / hygiene | Not loaded at runtime; fix through regular dependency and base image updates |
Two rules make the model robust. First, re-evaluate continuously: EPSS changes daily, KEV grows and a deployment can make a previously unreachable path reachable. Linking findings to deployment tracking shows when a release introduced or removed a vulnerable version. Second, document exceptions: if a P1 cannot be patched, record the compensating control (for example a WAF rule or feature flag) and an expiry date.
SLAs per priority (example)
Remediation targets make priorities binding. The values below are examples only, not a recommendation or a regulatory requirement; align them with your own risk appetite, contracts and any obligations that apply to you. Treat them like an internal SLA and map P1 to your incident severity levels if a finding is actively exploited against you.
| Priority | Example remediation target | Example escalation |
|---|---|---|
| P1 | Mitigate within 48 hours, fix within 7 days | Security lead and service owner immediately; incident if exploitation is observed |
| P2 | 30 days | Team lead after 50 % of the target |
| P3 | 90 days | Monthly review |
| P4 | Next scheduled dependency or image update | Quarterly hygiene report |
A runbook per priority, covering who is notified, how to mitigate temporarily and how to verify the fix, keeps the process consistent across teams.
How to measure progress
The total number of open CVEs is a poor metric: it grows whenever scanners add coverage and says nothing about risk. Track a few metrics that reflect exposure instead:
- Mean time to remediate (MTTR) per priority: from detection to verified fix, reported separately for P1 to P4. A falling P1 MTTR is the clearest sign of progress.
- SLA adherence per priority: share of findings fixed within the target.
- Open KEV-listed CVEs: number and share of open findings that appear in the CISA KEV catalog, ideally split into loaded and not loaded. The target for loaded, exposed KEV findings is zero.
- Exposure trend: number of findings that are both loaded and internet-exposed, per team.
- Unowned findings: findings on services without an owner in the service catalog. This number should go to zero first.
- Exceptions: open risk acceptances and how many have passed their expiry date.
Report these metrics per team. Too many low-value tickets cause the same fatigue as noisy alerts; the principles from reducing alert fatigue apply to security findings as well.
Copyable vulnerability triage checklist
Use this checklist for every new finding or batch of findings, for example in a weekly triage meeting or as a ticket template:
VULNERABILITY TRIAGE CHECKLIST
CVE / finding ID: ______________ Component + version: ______________
Affected services: ______________ Owner (team / on-call): ______________
[ ] 1. Deduplicate: same component across services = one decision
[ ] 2. CVSS: Base score + vector noted (CVSS-B); environmental adjustment needed?
[ ] 3. EPSS: probability ____ and percentile ____ (date: ____)
[ ] 4. CISA KEV: listed? yes / no (date added: ____)
[ ] 5. Runtime: library loaded in production? yes / no / unknown
[ ] 6. Reachability: vulnerable code path executed (traces/profiles)? yes / no / unknown
[ ] 7. Exposure: internet-facing? directly / indirectly / internal only
[ ] 8. Data: processes personal, payment or credential data? yes / no
[ ] 9. Priority assigned (P1-P4) and rule that applied: ______________
[ ] 10. Fix path: upgrade / patch / config change / remove dependency
[ ] 11. Interim mitigation if fix is delayed: ______________ (expiry: ____)
[ ] 12. Due date according to SLA: ______________
[ ] 13. Fix verified in production (version no longer loaded): ______________
[ ] 14. "Unknown" answers escalated to improve telemetry coverage
"Unknown" is a valid answer, but treat it as the worse case until the runtime data is available, and track how often it occurs: it is a direct measure of missing visibility.
How Obseria helps
Obseria connects vulnerability findings with the runtime data that observability already collects. Obseria Application Security runs in the existing Obseria Agent and scores vulnerabilities by whether the code is loaded, reachable from the internet and touching sensitive data, then routes findings to the teams that own the services. The security and reliability use case shows how this fits into incident and release workflows.
- Runtime vulnerability analytics with exposure and reachability scoring, plus container and library SBOM visibility.
- Ownership from the service catalog and release context from deployment tracking.
- Release gates for critical findings and automated routing to ticketing and chat tools.
- For teams without capacity to run this themselves: managed observability and security with our implementation partner.
Want to see which of your CVEs actually matter? Start a free trial and connect your first services.