ASPM · Jun 23, 2026 · 7 min read

A risk score is only as good as the proof under it

Ranking 500 unverified findings by CVSS is sorting noise. A risk score earns trust when exploitability is proven and business context is real.

A risk score is a number that asks you to trust it. It compresses hundreds of findings into a single figure a director can read in a meeting, and the whole point is that you act on it without re-deriving it by hand. That is exactly why the number is dangerous: it inherits the trust of its inputs, and nothing on the dashboard tells you whether those inputs were proven or merely asserted. A confident-looking 87 built on a queue of unverified findings is worth less than an honest 41 built on facts.

Most platforms compute the same kind of score we do - a weighted blend of severity, exploitability and asset context. The arithmetic is not the hard part. The hard part is the guarantee underneath every term: that each finding feeding the sum survived a proof step before it was allowed to move the number at all.

01A score inherits the trust of its inputs

Garbage in does not produce obvious garbage out; it produces a clean, plausible number that is quietly wrong. If a scanner raises a finding because a route returned 200, that unproven item still carries a severity label, still counts as a source, and still pushes the asset's risk band upward. The score looks authoritative precisely because it hides the weakness of what went into it. Sort by it and you spend your week on the loudest noise, not the realest danger. And our risk score is deterministic. The same inputs always yield the same integer, which is what makes it auditable - you can reconstruct any number from the findings beneath it. Determinism is necessary but not sufficient: a deterministic function of unproven findings is just a repeatable mistake. The defensibility comes from the proof gate that runs before a finding is ever counted, not from the formula that counts it.

02The weighted sum, term by term

The score starts from the finding's severity band and adds bounded bonuses for the things that make a vulnerability more dangerous in practice: that it was exploit-confirmed, that more than one independent source corroborates it, and that it lives on a production asset. The pipeline is short and every term is grounded in something we can point at:

severity band ──► base critical 90 / high 70 / medium 45 / low 20 / info 5 exploit_confirmed ──► +12 proven, not asserted sources >= 2 ──► +8 two engines agree environment = prod ──► +6 blast radius is real false_positive ──► -40 feedback loop demotes noise = clamp(0..100) ──► RISK_BAND
risk_score(): a base from severity plus bounded, evidence-gated bonuses, clamped to 0-100, then mapped to a band. Each addend is a fact, not a guess.

Read that diagram as a contract. The +12 for exploit-confirmed is the largest single bonus, and it is the one most platforms hand out for free. We do not. The -40 for a finding marked false positive is deliberately brutal: when a human or the FP filter rejects an item, its influence on the score collapses, so noise cannot quietly inflate a band it never deserved.

TermWeightWhat has to be true
Severity base5 - 90The finding's class maps to a band: critical 90, high 70, medium 45, low 20, info 5.
Exploit confirmed+12An exploit or leak was demonstrated, not inferred from reachability.
Two or more sources+8At least two independent engines corroborate the same root cause.
Production asset+6The application's environment is prod, so the blast radius is live.
False positive-40A reviewer or the FP filter rejected it; its weight is stripped out.

03Why confirmed and reachable are not the same input

The +12 hinges on a distinction most tools erase. Reachable means an attacker can get to the vulnerable sink; confirmed means we drove that sink and it gave up something it should not have. They are different facts, and only the second one earns the exploitability bonus. A finding that is merely reachable can describe a risk and be prioritized, but it cannot self-certify as proven - the exploit evidence is the only thing allowed to flip that bit.

finding A exploit_status = reachable ──► base only likely, not counted as proven finding B exploit_status = confirmed ──► base + 12 differential / in-band proof same severity, same asset, +12 apart ──► different band, different SLA clock
Two findings of identical severity diverge by 12 points purely on whether the exploit was demonstrated. Proof is the swing vote.

This is what stops the score from being inflated by potential. A platform that treats reachable and confirmed as one number reports a queue that looks more dangerous than it is, and the team learns to distrust the ranking. We keep the two states separate so the top of the queue is genuinely the top: the items that were proven, on assets that matter, corroborated by more than one engine.

04The band sets the clock

The score is not the end of the story; the band it maps to starts an SLA clock from the moment the vulnerability was first seen. This is where a poisoned score stops being an abstract worry and starts costing money: an unproven finding that inflated an asset into the critical band hands your team a 7-day remediation deadline it never actually owed, burning the exact engineering hours a real critical needed.

BandScore >=SLA from first seen
Critical907 days
High7030 days
Medium4560 days
Low2090 days
Info5120 days

Those windows roll up further. The org-level posture score starts at 100 and subtracts bounded penalties for open criticals, exploit-confirmed findings, SLA-breached items and slow MTTR, then maps to an A-F grade where A is 90 or above. Every one of those penalties traces back to individual findings, so a single unproven critical does not just mis-rank one asset - it drags the board grade and the trend line with it.

05One unproven finding poisons the whole number

Because the score is a sum, a false input is not isolated to its own row. It lifts the asset's band, restarts an SLA clock, adds a penalty to the posture grade and shifts the trend an executive reviews. The number still reconciles to its inputs perfectly, which is the trap: the math is honest and the answer is wrong, because honesty about arithmetic is not the same as truth about findings.

So the discipline that makes the score defensible is not in the scoring function at all - it is upstream, in the refusal to raise anything we did not prove. Severity, source-count and business context only get to vote once a finding has earned its place through in-band, differential or arithmetic evidence. Get that gate right and the weighted sum becomes what a risk score is supposed to be: a single number a security leader can defend in an audit, line by line, all the way down to the proof.

Evidence over heuristicsReachable beats foundMonitor → Block: rolling out a gate without slowing teamsIaC-grounded threat modelingAir-gapped AppSec with no phone-homeOne platform vs three tools
See it on your own app →