Reachability analysis determines whether a vulnerability can actually be reached in a specific environment, over the network, in the code, and by attacker-controlled data. It is the filter that makes exposure management tractable, because most flagged vulnerabilities cannot be reached in a way that matters.
Log4Shell is the clearest illustration. Every Java installation that shipped the Log4j library registered as vulnerable, and the flaw scored at the top of the severity scale. But if the application was not using that logging engine, the vulnerable code was never callable: loaded, and zero exposure. Severity said critical; the environment said there was nothing there to reach.
Multiply that across an estate and the consequence is straightforward. A backlog ranked by severity concentrates effort on findings no attacker could use, while genuinely exploitable exposures wait behind them. Reachability analysis turns an inventory of what is present into a shortlist of what is relevant.
In code the mechanism is the call graph. Static analysis builds the set of functions the application can invoke, follows the edges into dependencies and their transitive dependencies, and checks whether the vulnerable function appears on any path from an entry point. Taint analysis then adds the question of whether untrusted input can flow to it.
On assets the mechanism is more physical. File-path analysis rules out vulnerable components sitting in trash bins, backup folders or patch staging directories, because they are not in a runtime path. Port analysis establishes whether the host is listening on the port an exploit requires. Neither needs a runtime agent, which matters: agent-based instrumentation gives a strong signal where live traffic exercises a path and no finding at all where it does not.
Take one dependency reported as vulnerable across three services. In the first the library is listed in the manifest but the build strips it, so it is not present at runtime. In the second it is loaded on startup but the application uses a different logging implementation, so the vulnerable function is never called: loaded, not callable. In the third the function is called, but only with a constant string assembled internally, so no attacker-controlled data reaches the vulnerable parameter.
One CVE, one severity score, three different answers. Only the third case is close to exploitable, and even it requires checking whether any request path can influence that string. This is why a count of vulnerable components is a poor proxy for risk.
Vulnerability identifiers come from the CVE Program, with Log4Shell tracked as CVE-2021-44228. Component inventories are normally expressed in CycloneDX or SPDX format. Confirmed real-world exploitation is published by CISA in the Known Exploited Vulnerabilities catalog, and probability estimates come from the FIRST Exploit Prediction Scoring System.
Is reachability analysis the same as exploitability? Reachability is a large part of establishing exploitability, and not all of it. A reachable function still has to be exploitable in context.
Does reachability analysis need a runtime agent? Not necessarily. Static call-graph analysis on code, and file-path and port analysis on assets, both work without instrumentation.
Can a finding become reachable later? Yes. A control removed or a service newly exposed can change the answer, which is why findings that fail reachability should be retained rather than deleted.
How much does reachability reduce a backlog? It varies widely with the environment, language ecosystem and scanner mix. In dependency-heavy codebases most reported vulnerable components are never called.