Ask a security team why a finding is at the top of the list and the most common answer is a number: 9.8. It is a precise-sounding answer to the wrong question. A CVSS base score measures how bad a vulnerability could be in the abstract. It says nothing about whether anyone is exploiting it, whether the code is reachable, or whether the system holds anything worth stealing.

In short

  • CVSS rates the bug, not your exposure to it. More than half of all published CVEs score High or Critical, so sorting by CVSS still leaves thousands of urgent items.
  • Exploitation data changes the order. Only a small fraction of vulnerabilities are ever exploited. CISA’s KEV catalog and FIRST’s EPSS tell you which ones.
  • Your own context changes it again. Internet exposure, sensitive data, test-only code and compensating controls are facts your scanner cannot see.
  • The score must show its work. A developer who can see the factors argues with one line, not with the whole programme.

The problem with sorting by severity

Every scanner ships with a severity, and most of them borrow it from CVSS. CVSS was designed to describe the technical characteristics of a vulnerability consistently, and it does that well. The trouble starts when the base score is used as a to-do list.

Industry
data

Roughly 40,000 CVEs were published in 2024, the most ever recorded, and well over half of scored CVEs are rated High or Critical. Studies of exploitation consistently find that only a small share, typically in the low single-digit percentages, are ever seen exploited in the wild.

Sources: CVE Program and NVD publication statistics (2024); FIRST EPSS model documentation; Cyentia Institute & Kenna Security, Prioritization to Prediction series.

Put those two facts together and the arithmetic is unforgiving. If half of everything is “High or Critical”, severity cannot separate the urgent from the merely serious. Teams that sort by CVSS end up with a top of the list that is too long to finish, and they spend their remediation capacity on vulnerabilities nobody will ever use against them.

TODAY Sort by CVSS, fix from the top

Thousands of “criticals”, most never exploited. A critical in a test fixture outranks a medium on the payment API. Developers learn that the list is not a reliable signal.

WITH RISK CONTEXT Sort by likelihood × impact in your environment

Known exploitation and exploit probability decide likelihood; exposure, data and controls decide impact. The top of the list is short enough to finish and defensible line by line.

Three questions a priority has to answer

A useful priority answers three questions, in this order. CVSS answers part of the third.

1. Is anyone actually exploiting this?

Two free, public sources answer it. The CISA Known Exploited Vulnerabilities (KEV) catalog lists vulnerabilities with reliable evidence of exploitation in the wild; US federal agencies are required to fix them on a deadline, and it has become a de facto industry baseline. EPSS, the Exploit Prediction Scoring System from FIRST, estimates the probability that a vulnerability will be exploited in the next 30 days, updated daily from observed activity. KEV is the evidence; EPSS is the forecast.

2. Can it be reached here?

A vulnerable package that is only declared for development and testing is not shipped to production. A vulnerable library pulled in transitively is harder to reach than one your code calls directly. A service that is not reachable from any network is a smaller target than one on the public internet. Runtime evidence, such as a dynamic scan that triggered the issue or a detection on the running workload, settles the question in the other direction.

3. What happens if it is?

This is where business context lives: whether the service handles payment cards, personal or health data, how critical the business considers it, and whether a WAF or other control stands in front of it. None of this is in the scanner’s output. All of it is known to someone in your organisation.

flowchart LR A["Scanner result
CVE + CVSS"] --> B["1 · Exploited?
KEV, EPSS"] B --> C["2 · Reachable?
exposure, scope, runtime"] C --> D["3 · Impact?
data, criticality, controls"] D --> E["Score 0–10
every factor listed"] E --> F["P1–P4
with an SLA due date"] style E fill:#ccfbf1,stroke:#0d9488 style F fill:#99f6e4,stroke:#0f766e

Each question adds or removes points. The factors stay attached to the finding.

A score that shows its work

The most important design decision is not the weights. It is that every factor is kept and shown. In InsightFortify each finding carries a list of named factors with a signed contribution, and the priority is the sum. Here is a real breakdown from our demo estate, a vulnerable library in an internet-facing payments service:

FactorWhyContribution
CVSS 7.5the published base score7.5
Exploited in the wildlisted in the CISA KEV catalog+2.0
Internet-facingthe service is reachable from the internet+1.0
Handles sensitive dataPCI, PII as set on the repository+0.5
Compensating controlsWAF in front of the service−0.5
Scorekept within 0–10 without flattening the top9.6 → P1

And the other direction, a finding that a severity-sorted list would put near the top:

FactorWhyContribution
CVSS 9.8the published base score9.8
Exploitation unlikelyEPSS: well under 1% chance in the next 30 days−1.0
Dev-only dependencydeclared for development or test; not shipped−2.5
Score6.3 → P3

Neither result is surprising once the factors are visible. That is the point: a developer who thinks the “dev-only” factor is wrong can say so, and the conversation is about one fact rather than about whether the security tool can be trusted.

A finding in the InsightFortify console with its score breakdown, evidence and fix guidance
A finding’s detail page. Every factor that moved the score is listed with its contribution and the reason.

Where the context comes from

Context is only useful if someone maintains it, and it is only maintained if it is cheap to maintain. The design rule is to set it once, on the thing that owns it, and let every finding inherit it.

Where each factor is setSet once per asset; inherited by every finding on it
1
Exploitation (KEV, EPSS)automatic

Synced from CISA and FIRST every few hours. Nobody maintains it by hand.

2
Dependency scopeautomatic

Read from the package manifest: dev-only and transitive dependencies are marked by the scanner.

3
Test codeautomatic

Recognised from the path: tests, fixtures, examples.

4
Internet exposurerepository / cloud

Set on the repository, or derived from the cloud inventory: a public load balancer or a security group open to the world.

5
Data classesrepository / resource

PCI, PII, PHI on the repository; “sensitive” on a bucket or database in the cloud inventory.

6
Criticality and controlsrepository

Business criticality and compensating controls such as a WAF, agreed with the service owner.

7
Runtime evidenceDAST / Falco

A dynamic scan that triggered the issue, or a runtime detection on the workload, raises the score.

What changes for each audience

For the CISO

You can state a defensible policy: “we fix everything known to be exploited and reachable within seven days” is a sentence a board, an auditor and a regulator all understand.

The remediation SLA becomes achievable, because the P1 list is short enough to finish.

For the AppSec lead

Fewer arguments with engineering. Disagreements move from “your tool is noisy” to “this service is not internet-facing”, which is a fact you can check and fix.

Weights can be tuned centrally and every finding re-scores.

For the board

The headline number changes from “open critical vulnerabilities”, which only ever goes up, to “known-exploited, reachable vulnerabilities past their SLA”, which should trend to zero.

It is a number that means the same thing every quarter.

Pitfalls to avoid

  • Hiding the low scores. Deprioritised is not deleted. Keep every finding, keep the reason, and let auditors see both.
  • Trusting EPSS alone. It is a probability, not a verdict. A low EPSS on a vulnerability in your most exposed, most sensitive service still deserves attention. Combine it with impact.
  • Letting context go stale. A service that became internet-facing last quarter and is still marked internal will be under-scored. Derive exposure from the cloud inventory where you can, rather than from a form.
  • A black-box “AI risk score”. If the vendor cannot show you the factors, developers will not accept the priority, and you will not be able to defend it.

Measured on our own demo estate

Across two sample services, OWASP NodeGoat, a ZAP scan of OWASP Juice Shop and one AWS account, 382 raw scanner results correlated to 287 unique findings, and risk context reduced those to 131 actionable ones, a 66% reduction in what a developer is asked to act on. On NodeGoat alone, 340 raw results became 215 unique and 80 actionable. Your numbers will differ; the shape usually does not.

Severity tells you how bad a bug could be. Priority tells you what to do on Monday.

Build the priority from exploitation, reachability and impact, and show every factor that went into it.

Keep reading