1 · Executive summary
Every organisation with more findings than capacity is running a prioritisation model, whether or not it has written one down. Most are running the same one: sort by CVSS, work downwards, escalate whatever someone shouts about. That model is not merely imprecise — it is systematically wrong in a direction attackers benefit from.
The claim of this paper is narrow and testable. Severity describes a vulnerability. Risk describes a vulnerability in a place. Ranking by severity means ranking without the place, and the place is where nearly all of the variance lives: whether the code is reachable, whether the flaw is being exploited this month, whether the asset processes anything worth stealing, whether a control already stands in the way.
The uncomfortable arithmetic. A CVSS 9.8 in an unreachable code path on an internal batch worker is, in practice, close to a zero. A CVSS 6.5 authentication bypass on an internet-facing payment gateway with an inactive WAF rule is the most urgent item you own. A queue sorted by severity puts them in the wrong order, every day, and is defended on the grounds that it is objective.
What this paper provides
- An honest account of CVSS — what it measures, what its own specification says it is not for, and why the environmental metrics designed to fix this are almost never populated.
- Five signals — EPSS, KEV, reachability, business criticality and compensating controls — each with where to obtain it, what it is worth, and the failure mode nobody mentions.
- A composite model with the arithmetic shown, explicitly designed to be explainable rather than accurate to a decimal place.
- Ten findings ranked twice, by CVSS and by the model, so the disagreement is visible rather than asserted.
- The failure modes of prioritisation programmes, which are organisational more often than mathematical.
2 · What CVSS is, and what it was never for
CVSS is a good standard used badly. It exists to describe the intrinsic characteristics of a vulnerability in a way that is comparable across organisations — so that a flaw scored by a vendor in Helsinki means the same thing to a team in Bengaluru. That comparability is achieved precisely by excluding everything specific to your environment.
The standard is explicit that the base score is not a risk score, and it provides additional metric groups for the adjustment:
| Metric group | Describes | Who supplies it | Populated in practice? |
|---|---|---|---|
| Base | Intrinsic characteristics that do not change | Vendor or NVD | Always |
| Threat / Temporal | Exploit maturity, current state of the world | Consumer, from intelligence | Rarely |
| Environmental | Your deployment, your controls, your asset value | You | Almost never |
The third row is the whole problem. The mechanism to make CVSS environment-aware has existed for years and is not used, because populating it requires exactly the correlated context most organisations do not have: which asset, how exposed, how valuable, what compensates. So the base score is shipped raw into a work queue and treated as a priority.
The category error, in one line
Three specific distortions
Ceiling compression. A large fraction of published CVEs score between 7.0 and 10.0. Once a third of your queue is "critical", the label has stopped carrying information, and triage falls back to whoever is most persuasive in the meeting.
Uniform asset assumption. The same CVE on a developer's sandbox and on the host processing cardholder data scores identically. Every experienced practitioner corrects for this informally, which means the quality of your prioritisation depends on who is holding the spreadsheet that week.
No decay, no acceleration. A base score is the same the day a proof-of-concept lands on GitHub as it was the week before. The single most decision-relevant fact about a vulnerability — whether it is being exploited right now — is invisible to it.
3 · The five signals that change the answer
Each of these is obtainable today, by most organisations, without a platform. Each is also routinely misused, so each entry below states its failure mode as plainly as its value.
3.1 EPSS — is this likely to be exploited?
The Exploit Prediction Scoring System publishes, for most published CVEs, a probability that the vulnerability will see exploitation activity in the near term. It is a statistical model trained on observed exploitation, and it is free.
Its practical value is enormous, because the distribution is extremely skewed: the overwhelming majority of CVEs have very low probabilities, and a small minority carry most of the risk. Used as a filter rather than a ranking, EPSS removes a large share of a queue with a defensible justification.
Failure mode
EPSS is a population estimate, not a statement about your estate. It answers "how likely is this CVE to be exploited somewhere", not "how likely is it to be exploited here". Treating a high EPSS as evidence of targeting, or a low EPSS as permission to ignore something reachable and business-critical, both misread what the number is.
3.2 KEV — is it being exploited already?
CISA's Known Exploited Vulnerabilities catalogue lists vulnerabilities with confirmed, observed exploitation. Where EPSS is a prediction, KEV is a retrospective fact, and facts outrank predictions. Presence in KEV should be close to decisive: a KEV-listed vulnerability on a reachable asset belongs at the top of the queue almost regardless of its base score.
Failure mode
KEV is lagging and incomplete. Entry requires confirmed exploitation to have been observed and attributed, which happens after attacks begin, and its scope reflects the priorities of the authority maintaining it. Absence from KEV is not evidence of safety — it is absence of evidence.
3.3 Reachability — can anyone actually get there?
The single largest multiplier, and the most often missing. Reachability has layers, and the distinction matters because they cost different amounts to establish:
| Layer | Question | Where the answer lives |
|---|---|---|
| Network | Is the host or endpoint reachable, and from where? | Cloud topology, gateway and load balancer config, firewall rules |
| Authentication | Does reaching it require credentials? | Gateway policy, IAM, service configuration |
| Code path | Is the vulnerable function ever called? | Reachability analysis in modern SCA, call graphs |
| Data path | Can untrusted input arrive at it? | Threat model, architecture, taint analysis |
Most organisations can establish the first two within weeks from configuration they already hold. Those two alone reorder a queue more than any scoring refinement.
Failure mode
Reachability is a snapshot of a moving target. A service made internet-facing for a partner integration on Tuesday invalidates Monday's assessment silently. Reachability that is computed once and stored is a liability; it has to be recomputed on change.
3.4 Business criticality — what breaks if this fails?
The hardest of the five, because it cannot be derived from any scanner. It is a property of the business, recorded by people, and it decays as reorganisations happen.
Resist the temptation to build an elaborate scheme. Three or four tiers, consistently applied, outperform a ten-point scale nobody maintains. What matters is that the tier is attached to a service — something a customer would notice failing — rather than to a host, because hosts are replaced weekly and services are not.
Failure mode
Ask each team to rate their own service and everything becomes tier one. Ratings must come from a common owner applying a common definition — usually tied to regulatory scope, revenue dependency or customer-facing availability — and be reviewed on a schedule rather than on request.
3.5 Compensating controls — what already stands in the way?
A WAF rule in blocking mode, a network segment, an authentication requirement, a feature flag disabling the affected path. Each materially reduces real risk, and none of them changes a base score.
The critical discipline: a control counts only if its live state is verified. Paper 01 described a payment API whose WAF rule everyone cited in triage and which had been switched to detection mode during a performance incident four months earlier. That is not an unusual story. It is the normal behaviour of controls that live in people's memory rather than in data.
Failure mode
Compensating controls are the easiest place in the whole model to lie to yourself, because claiming one closes a finding. Any control that reduces a score should carry the date it was last verified, and an unverified control should count for nothing.
4 · Combining them without building a black box
There is a strong temptation to reach for machine learning here. Resist it for the first two years. The purpose of a prioritisation score is not to be optimal — it is to be agreed. An engineer who can see why item 1 outranks item 8 will work the list. One who is told the model decided will not, and will keep a private list instead, which is the state you were trying to leave.
A model that fits on an index card
Composite risk score
Multiplicative, not additive, because these factors compound: unreachable should collapse a score rather than subtract from it, and a verified blocking control should do most of the work of a fix while you schedule the fix.
The coefficients above are a starting point, not a truth. What matters far more than their exact values is that they are written down, few, and stable. Three properties make a model like this survive contact with an engineering team:
- Every factor is attributable. The score displays as
8.1 × 2.0 × 2.0 × 1.6 × 1.0, not as 96. Anyone can see which factor drove it and challenge that one specifically. - Nothing is hidden. If reachability data is missing, the model uses 1.0 and says so, rather than guessing. A queue with visible gaps is trusted; a queue with invisible assumptions is not.
- The coefficients change rarely and deliberately. A model tuned monthly cannot be compared quarter over quarter, so you lose the ability to say whether anything is improving.
The test of a prioritisation model is not whether it is right. It is whether the engineer who owns item 1 and item 8 can see why 1 comes first, and agrees.
5 · Ten findings, ranked twice
A composite of realistic findings from a mid-sized financial services estate. Columns: CVSS base, exposure, threat intelligence, service tier, verified control, and the resulting composite. Sorted by composite; the CVSS rank is shown for comparison.
| # | Finding | CVSS | Exposure | Threat | Tier | Control | Score | CVSS rank |
|---|---|---|---|---|---|---|---|---|
| 1 | Auth bypass, payment gateway | 6.5 | Internet, unauth ×2.0 | KEV ×2.0 | 1 ×1.6 | Unverified ×1.0 | 41.6 | 9th |
| 2 | RCE in edge proxy | 9.8 | Internet, unauth ×2.0 | EPSS high ×1.5 | 2 ×1.3 | Partial ×0.7 | 26.8 | 1st |
| 3 | SQLi, customer portal search | 8.6 | Internet, auth ×1.5 | EPSS mod ×1.2 | 1 ×1.6 | Unverified ×1.0 | 24.8 | 3rd |
| 4 | Deserialisation, partner API | 9.8 | Internet, auth ×1.5 | None ×1.0 | 2 ×1.3 | Unverified ×1.0 | 19.1 | 1st |
| 5 | Priv-esc, container runtime | 7.8 | Internal ×1.0 | KEV ×2.0 | 1 ×1.6 | Partial ×0.7 | 17.5 | 6th |
| 6 | XXE, internal reporting service | 8.2 | Internal ×1.0 | EPSS mod ×1.2 | 2 ×1.3 | Unverified ×1.0 | 12.8 | 5th |
| 7 | Stored XSS, admin console | 8.8 | Internal ×1.0 | None ×1.0 | 3 ×1.0 | Blocking ×0.4 | 3.5 | 2nd |
| 8 | Public bucket, marketing assets | 7.5 | Internet, unauth ×2.0 | None ×1.0 | 4 ×0.5 | Blocking ×0.4 | 3.0 | 7th |
| 9 | Deserialisation, batch worker | 9.8 | Unreachable ×0.1 | None ×1.0 | 3 ×1.0 | Unverified ×1.0 | 1.0 | 1st |
| 10 | Weak cipher, legacy internal API | 7.4 | Unreachable ×0.1 | None ×1.0 | 4 ×0.5 | Unverified ×1.0 | 0.4 | 8th |
What the disagreement tells you
The top item moved from ninth to first. A 6.5 outranks three 9.8s because it is unauthenticated, internet-facing, known to be exploited, and sits on a tier-one regulated service. Every one of those facts came from a system other than the scanner that reported it.
Three 9.8s spread across ranks 2, 4 and 9. Identical severity, wildly different risk. The one at rank 9 — unreachable, on a batch worker — would have consumed the first day of remediation effort under a CVSS-ordered queue.
Two findings dropped almost to zero because of verified controls. Note the word verified. Had those controls been assumed rather than checked, the model would have quietly buried two live issues, which is the most dangerous failure this design can produce — and the reason section 3.5 insists on a verification date.
Run this on your own data before you believe it. Take fifty open findings, add five columns, and compute the composite in a spreadsheet. It takes an afternoon. The disagreement between the two orderings is the business case for everything else in this paper — and if there is no disagreement, you did not need the platform.
6 · How prioritisation programmes fail
The mathematics is the easy part. These are the failure modes we see in practice, and all five are organisational.
-
False precision
A score of 87.3 implies an accuracy the inputs cannot support. Display bands — critical, high, moderate, low — and keep the number for ordering within a band. The moment someone argues about the difference between 87.3 and 86.9, the model has become the subject instead of the tool.
-
Gaming the criticality tier
When tier drives SLA, every service owner discovers their service is tier one. Tiering must be assigned by someone who does not own the remediation workload, against a written definition, and audited occasionally.
-
Exception debt
Risk acceptances accumulate, expire silently and are never revisited. Every acceptance needs an owner, an expiry date and a review that actually happens — otherwise the exception register becomes the real vulnerability register, unmanaged.
-
Unmaintained inputs
The model is only as current as its worst input. Exposure recomputed monthly on an estate that changes daily produces confident, stale answers. Every input needs a refresh interval and a visible age.
-
Ranking without capacity
A perfectly ranked queue of 300 items delivered to a team that can close 12 a week is still a demoralising queue. Prioritisation must be paired with a commitment about how far down the list the organisation actually intends to go — and honesty that the rest is accepted risk, whether or not anyone signed for it.
7 · Implementing it in the order that works
The order below is not arbitrary. Each stage is useful alone, and each makes the next one possible.
| Stage | Add | Typical effort | What it buys |
|---|---|---|---|
| 0 | Deduplicate findings | Days | Every metric below becomes meaningful; usually removes 25–60% |
| 1 | KEV flag | Hours | A free, public list join. The highest value-to-effort ratio available |
| 2 | Internet exposure | Weeks | The largest single reordering; from config you already hold |
| 3 | EPSS | Hours | Defensible de-prioritisation of the long tail |
| 4 | Service tier | Weeks, plus politics | Connects the queue to the business; the slowest and most valuable step |
| 5 | Verified control state | Ongoing | Removes false urgency, and finds controls that have quietly stopped working |
| 6 | Code-path reachability | Months | Refinement, not foundation. Do not start here |
Stages 1 and 3 can be completed in an afternoon each and require no platform. If you do nothing else from this paper, join your findings against KEV and against EPSS this week, and re-sort. The result will be closer to correct than what you have now, and it costs one query.
Notice that stage 6 — the one most vendors lead with — comes last. Code-path reachability is genuinely valuable and genuinely expensive, and it refines a queue that stages 0 to 5 have already made roughly right. Buying it first is the classic mistake: precision applied to an unranked, unowned, duplicated backlog.
8 · Knowing whether it worked
Prioritisation programmes are unusually easy to declare successful, because the obvious metric — findings closed — improves when you close easy things. Four measures that resist that:
| Measure | Definition | Why it resists gaming |
|---|---|---|
| Time to remediate, top decile | Median days to close for the top 10% by composite score | Closing easy low-risk items does not move it |
| Exposure-weighted open risk | Sum of composite scores still open | Falls only when genuinely risky items close |
| Queue depth at capacity | How far down the ranked list your team actually reaches each week | Makes the capacity conversation explicit |
| Ranking challenge rate | How often an engineer disputes a rank, and how often they are right | Measures whether the model is believed — the only thing that makes it work |
The fourth is the one to watch in the first quarter. A challenge rate near zero usually means nobody is reading the ranking, not that it is perfect. A challenge rate that starts high and falls, with the model corrected along the way, is what adoption actually looks like.
9 · How Prak Knit does this
Everything above is implementable without us, and section 7 is deliberately written so you can start on Monday with a spreadsheet.
Klair Vu implements this model over correlated data. Findings are deduplicated on arrival, joined to an application, a business unit and a service tier, and scored on exposure, KEV and EPSS status, criticality and verified control state. The score displays with its factors visible, so an engineer can see that an item ranks first because it is unauthenticated, internet-facing and KEV-listed — and can challenge exactly that, rather than the number.
Where a factor is unknown, it is shown as unknown and treated as neutral, never guessed. Unmapped findings are surfaced as a gap in the programme rather than silently defaulted, because a queue that hides its own blind spots is the thing this paper exists to argue against.
Severity is not risk.
Bring fifty of your open findings to a walkthrough and we will rank them both ways, in front of you.
Book a demo Read paper 01: the visibility crisis