Reachability Triage
also called Exploitability Prioritisation, Vulnerability Relevance
Prioritising dependency vulnerabilities by whether the vulnerable code path is actually reachable and exploitable in your application, rather than by severity score - which is what makes vulnerability management survivable.
A scanner reports every known vulnerability in every dependency, including code paths the application never calls. Treating them all as equivalent produces a backlog large enough that nothing is prioritised, teams add blanket exceptions, and the control stops operating.
Reachability triage asks whether the vulnerable function is called, whether the input reaches it, and whether the conditions for exploitation exist in this deployment.
Why it matters
The finding count is not a security outcome; time to remediate exploitable findings is. Optimising the first — by blocking builds on any vulnerability of any severity — reliably worsens the second, because the noise trains teams to bypass the control.
It also focuses effort where it changes risk. A critical vulnerability in an unused code path is a different problem from a medium one in the request-handling path, and severity scores cannot make that distinction because they are computed without knowing your application.
Implementation patterns
- Generate the dependency inventory from the build, not by hand, so a disclosure is answered by a query rather than a search — a difference of days.
- Use call-graph analysis where available to determine whether the vulnerable symbol is reachable.
- Consider deployment context: is the affected feature enabled, is the input attacker-controlled, is the component network-exposed.
- Block the build only on reachable, exploitable findings, and route the rest to a tracked backlog with an owner.
- Measure time-to-remediate for the exploitable class, which is the metric that reflects risk.
- Pin and verify dependencies with lock files and integrity hashes, so the artefact is reproducible and a compromised registry cannot silently substitute.
- Isolate build environments with no ambient credentials, since a build that can reach production secrets turns any dependency into a path to them.
- Restrict runtime capability — egress controls, filesystem limits — which reduces the value of a compromise regardless of how it arrived.
Industry example
A data-protection platform such as Druva illustrates why the dependency question is architectural rather than procedural: a compromised dependency in a backup agent is a route into every customer's estate. That changes the calculus for which components deserve deep scrutiny and runtime restriction, and it argues for a documented trust decision per dependency in the highest-privilege components.
Failure scenarios
- Blocking on every finding, producing exceptions that disable the control.
- A report nobody triages, which is the most common state.
- A manually maintained inventory, wrong within a sprint.
- Severity-driven prioritisation, spending effort on unreachable criticals while a reachable medium sits.
- No fast patch path, so even correct prioritisation cannot be acted on before exploitation.
Trade-offs
Reachability analysis is imperfect: dynamic dispatch, reflection and configuration-driven code paths defeat static analysis, and a false negative means a real vulnerability is deprioritised. It also requires tooling maturity that not every language ecosystem has.
The honest position is that it is a prioritisation aid rather than a decision procedure — the unreachable findings are still patched, just on a normal cadence rather than as an emergency. That framing avoids the failure where reachability becomes a reason not to patch at all.
Interview question
"Your scanner reports four hundred vulnerabilities across your services, twelve of them critical. What do you do this week, what do you do this quarter, and how do you decide which twelve are actually the important ones — which may not be the twelve marked critical?"