Tensor LabsTENSORLABS

Six of your four hundred security alerts are real

Call-graph reachability analysis ranks a security backlog by whether the vulnerable code can ever run, turning 417 alerts into six with evidence.

July 27, 20264 min read4 sectionsBy Ahmed Abdullah
A red and black control panel with rows of numbered connector ports

417 alerts, and no way to rank them

The SOC 2 prep call had been going fine for forty minutes, right up until the auditor shared his screen. The dependency scanner showed 417 open vulnerability alerts, 63 of them critical, the oldest dated fourteen months back. The CTO looked at the wall of red and asked the question that was really a confession: "Does anyone actually know which of these matter?"

Silence. Then the head of engineering, honestly: "We triage the criticals when a customer asks."

Nobody in that room was negligent. The backlog was unworkable by design. Every alert said the same thing, a CVE number and a severity score computed by people who have never seen this codebase, and clearing one took an engineer twenty minutes to conclude, four times out of five, that the vulnerable function could never run here. Four hundred alerts at twenty minutes each is more than three engineer-weeks of work that mostly proves nothing was wrong. So the queue grew, the criticals aged, and the team developed the only rational habit available: ignore the scanner, pay attention to customers.

A security backlog nobody can rank is not caution. It is a growing pile of unread mail with a compliance deadline attached.

Why a CVSS score is not exposure

A CVSS score describes the vulnerability in the abstract: how bad it would be if the vulnerable code ran with attacker-controlled input. It says nothing about whether your application can ever reach that code. Most of the time, it cannot. The vulnerable function sits in a corner of a transitive dependency your code never calls, behind a feature flag you never enabled, in a parser for a format you never accept.

Industry analyses of reachability put the share of vulnerability alerts that are actually exploitable in context at somewhere between 2 and 15 percent. Call it one in ten as a generous average. The other nine are technically true statements about code you ship and never execute, each one indistinguishable, on the dashboard, from the one that can hurt you.

Rank by whether the code can run, not how scary it sounds

The method is reachability analysis, and it changes the unit of work from "vulnerability" to "vulnerability my application can actually reach." Static call-graph analysis walks from your application's entry points through every function call, across your own code and into your dependencies, and asks for each vulnerable function: does any path lead here? No path, no exposure, down the queue it goes with the reason recorded. A path exists, and now the alert carries evidence: the chain of calls from your route handler to the vulnerable code, which is precisely the artifact an auditor accepts and an engineer can act on.

Layer runtime signal on top and the ranking sharpens further: instrument what actually loads and executes in production, because a reachable-in-theory function that has never once loaded in six months of traffic is a different conversation from one that runs on every request. We built this pass into our own dependency pipeline after a critical-labeled alert sat for a quarter and turned out to be unreachable, while a medium two screens below it was sitting in a hot path.

(The tooling has names. OSV plus call-graph reachability in Semgrep or Snyk's reachability engine, runtime SBOMs, VEX statements for the paperwork. The acronyms are optional; the call graph is not.)

For the team on that SOC 2 call, the arithmetic moved decisively. Of 417 alerts, reachability analysis confirmed a path for 31. Runtime evidence narrowed the urgent set to six, each with a documented call chain. Six is a Tuesday. The other 386 closed in bulk with machine-generated justifications the auditor read, sampled, and accepted.

Why the scanner cannot do this for you

Reachability is not a setting you enable. Call graphs in dynamic languages need careful handling of reflection, dependency injection, and framework magic, or they silently miss paths and lie to you in the dangerous direction. Entry-point inventories have to match how your services actually deploy. Runtime instrumentation has to be cheap enough to leave on. This is static-analysis engineering, a specialist's craft, and the difference between owning it and not owning it is the difference between six findings with evidence and 417 findings with a shrug.

TensorLabs builds reachability triage into engineering teams' pipelines so the security queue ranks itself. If your scanner's number has three digits and your honest answer to "which of these matter" is a guess, send us the number. We will sketch what a call-graph pass usually does to one like it.