# Vulnerability Prioritization

> Vulnerability prioritization ranks vulnerabilities by the risk each poses in your system, using reachability, exploitation, EPSS, and CVSS, not severity alone.

Also known as: risk-based vulnerability management, RBVM, risk-based prioritization, contextual vulnerability prioritization, CVE prioritization

Source: https://socket.dev/glossary/vulnerability-prioritization

Last updated: 2026-10-21

Vulnerability prioritization is the practice of ranking known vulnerabilities by the risk each one poses in your specific system, not by severity score alone, so scarce remediation effort lands on the few that matter. It combines reachability analysis, known exploitation ([CISA KEV](https://socket.dev/glossary/cisa-kev)), exploit probability ([EPSS](https://socket.dev/glossary/exploit-prediction-scoring-systems-epss)), and [CVSS](https://socket.dev/glossary/common-vulnerability-scoring-system) severity into one ordered queue.

We ran `npm audit` on a nine-package lockfile and got 77 distinct CVE advisories. CVSS rates 38 of them high or critical. Four carry an EPSS probability above 0.10. Zero appear in the CISA KEV catalog. Three signals, three incompatible answers about what to fix. Our position: gate on reachability first, treat known exploitation as a hard override, sort the remainder by EPSS, and use CVSS only to break ties.

## What is vulnerability prioritization?

Vulnerability prioritization is the decision stage of [risk-based vulnerability management](https://socket.dev/glossary/vulnerability-management): the step that takes a flat list of findings and puts it in the order you should fix them. [Vulnerability scanning](https://socket.dev/glossary/vulnerability-scanning) produces the inventory by matching your software against [CVE](https://socket.dev/glossary/common-vulnerabilities-and-exposures-cve) records. Prioritization decides which of those findings is worth an engineer's time this week.

The step exists because the inventory is enormous and the capacity to fix is not. [48,185 CVEs were published in 2025](https://socket.dev/blog/cve-volume-surges-past-48k-in-2025), and submissions keep climbing: NIST cited a 263% rise between 2020 and 2025 when it [stopped enriching most records](https://socket.dev/blog/nist-officially-stops-enriching-most-cves). A 2025 survey of 82 studies on vulnerability prioritization sorts the signals into five families: severity, exploitability, contextual, predictive, and aggregated. Four of them do the real work, and they disagree sharply about the same findings.

> Three prioritization signals applied to the same 77 CVE advisories from one npm lockfile: CVSS 7 or higher keeps 38, EPSS 0.10 or higher keeps 4, CISA KEV keeps 0.

The figure shows one npm lockfile's 77 CVE advisories filtered by each signal on October 20, 2026. CVSS 7.0 or higher keeps 38. An EPSS probability of 0.10 or higher keeps 4: the `mongoose`, `lodash`, `qs`, and `moment` advisories. CISA KEV keeps 0. The three queues barely overlap, which is the whole problem: pick the wrong signal and you spend the week on the wrong 38.

```bash
$ cat package.json | python3 -c 'import json,sys;print(len(json.load(sys.stdin)["dependencies"]))'
9

$ npm install --package-lock-only --ignore-scripts
$ npm audit --json | python3 -c 'import json,sys;print(json.load(sys.stdin)["metadata"]["vulnerabilities"])'
{'info': 0, 'low': 4, 'moderate': 3, 'high': 15, 'critical': 1, 'total': 23}
```

npm audit counts 23 vulnerable packages. Expanded to one row per advisory, that is 77 CVEs across direct and transitive dependencies. The counting unit alone changes the number a dashboard reports by 3x, before anyone has ranked anything.

## Why does a CVSS score rank vulnerabilities poorly?

A CVSS base score ranks vulnerabilities poorly because it describes the flaw in the abstract and knows nothing about your deployment. FIRST, which maintains CVSS, says the base score is meant to be refined by temporal and environmental metrics, not used alone. Two failures show up constantly in open source dependencies: context blindness and identity drift.

Context blindness: CVE-2026-25645 flags every project on `requests` below 2.33.0. The maintainers' advisory narrows it to almost nobody. *“Standard usage of the Requests library is not affected by this vulnerability,”* it states, and only code that calls `requests.utils.extract_zipped_paths()` directly is exposed. A CVSS number cannot tell you whether your code reaches that function; [reachability analysis](https://socket.dev/glossary/reachability-analysis) can.

Identity drift: scanners disagree about the same CVE because they read different records of it. The [NVD](https://socket.dev/glossary/national-vulnerability-database-nvd) and the GitHub Advisory Database assign conflicting CVSS scores to roughly 1,500 CVEs, with gaps as wide as 6.9 points, enough to move a finding from “next month” to “tonight.” Worse, one mongoose prototype-pollution flaw in our lockfile exists under two different CVE IDs with two different scores.

```bash
$ curl -s https://cveawg.mitre.org/api/cve/CVE-2022-24304 \
    | python3 -c 'import json,sys;d=json.load(sys.stdin);print(d["cveMetadata"]["state"])'
REJECTED
# "This candidate is a duplicate of CVE-2022-2564."
```

CVE-2022-24304 was rejected as a duplicate of CVE-2022-2564. The two describe the same `mongoose` Schema.path() bug. A scanner keyed on the dead ID either double-counts it or drops it, and CVE-2022-2564 happens to carry the highest EPSS score in the whole lockfile (0.313, the 98th percentile). The highest-value finding is the one most likely to be mislabeled.

## How do you prioritize vulnerability scan results?

Prioritize vulnerability scan results by applying the cheapest decisive signal first and stopping as soon as a finding is settled. The order that works is reachability, then known exploitation, then exploit probability, then severity.

**Gate on reachability.** If your code cannot reach the vulnerable function, the CVE cannot hurt you, whatever its score. This removes the most findings, so it goes first.

**Override on known exploitation.** If a reachable CVE is in CISA KEV, fix it now. KEV lists only CVEs with confirmed exploitation in the wild: 1,754 of them as of catalog version 2026.10.20, under 0.4% of a single year's CVEs. Membership is rare and decisive.

**Sort the rest by EPSS.** EPSS estimates the probability a CVE will be exploited in the next 30 days. FIRST measured that prioritizing everything at EPSS 0.10 or higher reaches 65.2% efficiency, against 3.96% for a “fix all CVSS 7+” strategy, while touching a fraction of the list. FIRST calls the 0.10 cutoff arbitrary, so treat it as a dial, not a law.

**Break ties with CVSS.** CVSS severity is the last input, not the first. It is useful for ordering two findings that are otherwise equal, and misleading as a primary sort.

These four signals, plus the decision framework [SSVC](https://socket.dev/glossary/stakeholder-specific-vulnerability-categorization), answer different questions and fail in different ways. The table is the short version.

| Signal | Question it answers | Keyed on | Fails when | Use it to |
| --- | --- | --- | --- | --- |
| Reachability | Does our code reach the flaw? | Call graph into the dependency | Dynamic loading, reflection obscure the path | Discard unreachable CVEs first |
| CISA KEV | Is it exploited in the wild now? | CVE ID | Attack has no CVE; evidence lags | Force an immediate fix |
| EPSS | How likely is exploitation soon? | CVE ID | New CVEs with no history score low | Order the long tail |
| CVSS | How bad is the flaw in theory? | CVE ID | Ignores your context entirely | Break ties only |

Verdict: start with reachability to delete what your code never calls, let KEV override everything reachable, order the remainder by EPSS, and keep CVSS for ties. None of the four, in any order, can rank a threat that was never assigned a CVE.

## What is contextual vulnerability prioritization?

Contextual vulnerability prioritization is ranking that uses the facts a severity score omits: whether the vulnerable code is reachable, whether the asset is exposed, and whether the flaw is being exploited. Reachability is the sharpest of these for open source dependencies, because most of a CVE's blast radius is a single function you probably never call.

Take the lodash advisories in our lockfile. CVE-2021-23337 is command injection through `lodash`'s `_.template` function. CVE-2026-4800 is the 2026 follow-up: the fix for the first bug validated the `variable` option but not `options.imports` key names, and both flow into the same `Function()` sink. Both are reachable only if your application passes untrusted input to `_.template`.

Almost no application uses `_.template` with attacker-controlled input; the common calls are `_.get`, `_.map`, `_.cloneDeep`. For those projects, both lodash CVEs are unreachable and belong at the bottom of the queue, regardless of their 7.2 and 8.1 CVSS scores. Socket's Full Application Reachability builds a call graph from your code into each dependency and [typically marks about 80% of CVE findings unreachable](https://socket.dev/blog/introducing-tier-1-reachability), more than 90% in some ecosystems. It runs with `socket scan create --reach` and shows the exact call path when a finding is reachable. The analysis over-approximates: when it cannot prove no path exists, it reports the CVE as reachable rather than hide it.

## The queue only ranks what has a CVE

Every signal in this article keys on a CVE. That is also the ceiling. Reachability, KEV, EPSS, and CVSS all assume the dangerous thing is a disclosed flaw in legitimate code, reached through your [transitive dependencies](https://socket.dev/glossary/transitive-dependency). A malicious package is not a flaw; it is working code doing what its author intended, and it rarely gets a CVE. During [the axios compromise](https://socket.dev/blog/hidden-blast-radius-of-the-axios-compromise) in March 2026, a release pulled in a malicious dependency that executed at install time and left no entry any CVE queue would rank. The lockfile looked clean afterward.

So prioritization earns its keep and then stops. A queue ordered by reachability, exploitation, and probability is far shorter and far closer to real risk than one ordered by CVSS. It is also blind to the fastest-moving supply chain attacks, which never pass through the CVE pipeline at all. The sharpest ranking in the world cannot sort a threat that was never assigned a number.
