Your scanner just told you that you have 147 critical vulnerabilities. I'm going to tell you the truth that your CISO's dashboard won't: almost none of them matter, and the fact that you're about to spend your week on them is a bigger security problem than any of the CVEs on the list.
The number is a lie, and everyone selling you the number knows it
Here is what actually happens when you run a modern container scanner against a production image. Trivy, Grype, whatever — pick your poison. You scan node:20-slim or some python:3.12 base, and the tool lights up like a Christmas tree. One hundred, two hundred, three hundred findings. A satisfying wall of red. "CRITICAL" in a font engineered to make your adrenal glands twitch.
Now do the thing nobody does: actually read them.
Your 147 criticals collapse, almost every time, into the same tired cast of characters. A glibc CVE the Debian security tracker has already marked "minor," unfixed because it isn't remotely exploitable in any realistic configuration. A zlib finding like CVE-2023-45853 — the minizip integer overflow — that Debian flags as not affecting the package at all, because Debian doesn't even build the vulnerable component, and yet Grype cheerfully reports it CRITICAL on half the images on Docker Hub. A pile of libssl issues fixed upstream but not in the distro's stable channel, so there is no patched version to upgrade to. A perl CVE in a package that exists in the image only because apt pulled it in, and which never runs at request time, ever.
A vulnerability with no reachable code path and no available patch is not a vulnerability you have. It's a vulnerability you're being billed for, in engineering hours.
Strip out the unreachable, the unpatchable, and the base-layer noise, and your 147 criticals become four things worth a conversation and maybe one worth doing tonight. But the dashboard says 147. The compliance auditor sees 147. The quarterly board slide says 147. So a team of smart people spends Thursday chasing a number that describes their scanner's default settings far better than it describes their risk.
CVSS is a severity score for a vulnerability that has never seen your architecture
The base CVSS score — the one that earns the CRITICAL badge — is computed by someone who has never seen your network, your deployment, your WAF, your NetworkPolicies, or whether the affected function is even in your call graph. It is, by design, a worst-case abstraction. A 9.8 means "if every environmental assumption breaks in the attacker's favor, this is bad."
That's a useful thing for a CVE database to publish. It is a catastrophic thing to triage on.
Because the score is context-free, it's also trivially gamed. Reporters inflate CVSS vectors to farm attention and bug-bounty payouts — mark a needs-root-already, local-only bug as Network / Low-complexity / No-privileges and watch it rocket to 9.1. Vendors quietly deflate them to protect their dashboards. NVD's analysts, so backlogged that in 2024 they simply stopped enriching thousands of CVEs for months, rubber-stamp vectors nobody deeply validated. The number that governs your entire remediation pipeline is produced by an incentive structure that rewards everything except accuracy.
And the scanners inherit all of it, uncritically. They match a package name and a version range against a feed and paint it red. They don't know the vulnerable method is dead code in your build. They don't know the port isn't exposed. They don't know a NetworkPolicy turns the "network" attack vector into a fantasy. They can't know, and they don't claim to — but the org treats their output as a verdict instead of a lead.
The real damage isn't the false positives. It's what chasing them does to your team.
I can live with a noisy tool. What I can't live with is what the noise does to human beings over time.
When you make a competent engineer burn a fourth consecutive sprint on "criticals" they can see with their own eyes are unreachable, unpatchable garbage, you teach them one lesson with brutal efficiency: the security queue is bullshit. You are training your best people to close tickets without reading them, to slap a --severity HIGH,CRITICAL filter on and mash "won't fix," to treat the entire security function as a compliance tax rather than a discipline.
Because the one week you ship a genuinely reachable, genuinely exploitable RCE in a dependency you actually call — the log4j, the real one — it lands in a queue of 300 findings everyone has already trained themselves to swipe past. Log4Shell was CVSS 10.0, EPSS pinned near the ceiling, on CISA's KEV within days — and it still sat unpatched in thousands of orgs for weeks, because it was one red line in a sea of red lines. You built a smoke detector that shrieks when you make toast, then act surprised nobody moved during the fire. This isn't hypothetical. It's the post-mortem of half the incidents I've read.
Triage on exploitability and reachability, or don't triage at all
Here's the position I'll defend against anyone: raw vulnerability count is not a security metric. It's a procurement metric. The only questions that matter:
- Is the vulnerable code actually reachable from an entry point in my deployment?
- Is there a weaponized exploit path — and does my environment enable it?
- Is there a fix I can actually apply?
If the first two are no, the finding is not urgent no matter what color it is. If the third is no, screaming about it changes nothing but your team's morale.
The good news: this is no longer a manual thought experiment. The tooling exists, and there's no excuse left for triaging on base scores.
- Reachability analysis. Tools that trace whether the vulnerable symbol is in your actual call graph — Endor Labs, Snyk's reachability, open work like Google's
capslockfor Go — routinely discard the large majority of findings as unreachable; vendors put the reduction at 80–95%. Take that as a strong signal, not a proof. Static analysis has real blind spots: reflection, dynamic dispatch, config- and plugin-driven calls, serialization gadgets (Log4Shell itself was reachable through a path a naive call-graph walk misses), and code that becomes reachable after the next refactor or base-image rebuild. Reachability shrinks the queue dramatically and honestly. It doesn't get to pronounce a CVE dead on its own. - EPSS, the Exploit Prediction Scoring System, gives an empirical probability a CVE gets exploited in the wild within 30 days. The overwhelming majority of 9.8s sit under 1%. Sort by EPSS and the list reorders itself into sanity.
- CISA KEV — the Known Exploited Vulnerabilities catalog — is the single highest-signal feed in this industry. It's a list of things being used against people right now. If a CVE is on KEV and reachable in your stack, that's your night. Well under 1% of all CVEs ever land on it. Everything else can wait.
- VEX (Vulnerability Exploitability eXchange) lets upstreams and your own team assert "not affected, here's why" in a machine-readable form, so the same debunked zlib finding stops resurfacing every single scan until the heat death of the universe.
Wire those into the pipeline and the workflow inverts. Instead of "here are 147 criticals, go," you get "here are two findings that are reachable, have a published exploit, are on KEV, and have a patch." That's a queue a human can respect. That's a queue people actually act on.
What I'm actually asking you to do
Stop reporting counts. Kill the "criticals over time" burndown chart — it measures your scanner's verbosity, not your posture. When leadership asks "how many criticals do we have," refuse the premise and answer the real question: "how many reachable, exploitable, patchable issues are open, and what's the oldest one." If your tooling can't answer that, that's the gap — not the CVE count.
And yes — some of those counts are load-bearing. FedRAMP, PCI-DSS, a customer contract with a 30-day-patch SLA: sometimes you do have to remediate an unreachable, unpatchable CVE because an auditor or a contract says so, reachability be damned. That's real, and pretending otherwise is its own kind of dishonesty. But it's an argument for a separate compliance track with its own clock and its own owner — not for letting a base score set your security team's priorities. Don't confuse the paperwork you owe a regulator with the risk you owe your users.
Treat every context-free scanner finding as an unverified tip from an informant with a documented inflation problem — because that is exactly what it is. Reachability and exploitability aren't a nice-to-have refinement layered on top of the count. They are the triage. Everything else is theater we've agreed to perform so a dashboard can stay green while our best engineers quietly stop believing the alarm means anything.
The scanning industry sold us a number and called it security. Go find the signal underneath it.