By Adrian De Gendt
Supply chain security has shifted from a specialty concern to a standard AppSec workload. The SBOM movement, the proliferation of SCA tooling, and a series of high-profile compromises involving build infrastructure and package registries have made dependency inventory a baseline expectation for most engineering teams. What has not kept pace is the analysis layer that connects the dependency inventory to actual risk in a deployed application.
Knowing what is in your dependency tree is necessary but not sufficient. The question that determines whether a supply chain vulnerability represents a real exposure in your specific application is whether an attacker can reach the vulnerable component through an executable path from an entry point they control. That question requires the same analysis as any other reachability problem, with some additional complications that are specific to third-party code.
What supply chain risk adds to the reachability problem
When a vulnerability is in your own code, you know exactly what the code does. You can inspect the call sites, understand the data flow, and make an informed judgment about whether the vulnerable pattern is exercised by external inputs. With third-party library code, you have varying degrees of access to that context depending on whether the library is open source, how well documented it is, and whether the vulnerability description is precise enough to identify which specific function or behavior is the attack vector.
CVE descriptions for library vulnerabilities range from specific to vague. A precise CVE description names the vulnerable function, the input type that triggers the issue, and the affected versions. A vague description says "improper input validation in library X" without specifying where. For reachability analysis, the precision of the CVE description matters: you need to know which node in the call graph is the vulnerable point to determine whether it is on an exposure path.
Open-source libraries allow you to inspect the patch diff, which usually identifies the vulnerable function precisely. For a patched library, the diff shows exactly what changed, and from that you can identify the function that was vulnerable. For closed-source or proprietary components with limited CVE detail, reachability analysis has to operate at a coarser granularity: is the library invoked from any path from an exposed entry point? If yes, treat as potentially reachable until the CVE is resolved.
The transitive dependency problem at scale
A modern Node.js application might carry 600 to 1000 packages in its full dependency closure. A Java application using a popular framework stack similarly. The vast majority of these packages are transitive: they were not explicitly declared by the application developers but pulled in as dependencies of dependencies. Most of them are never directly invoked by application code; they exist in the dependency tree because something else needed them.
When a CVE is published for one of those transitive packages, the immediate question from an SCA tool is: do you have this package? Yes. Do you use a vulnerable version? Yes. But the triage-relevant question is: through how many hops does attacker-controlled data need to travel to reach the vulnerable function in this package, and do all those hops exist as executable paths in your application?
A transitive dependency five hops from your application code, where the intermediate hops include a utility function that processes only internal configuration data, is not the same risk as a direct dependency whose vulnerable function is called by a public API handler. Both show up as the same CVE in the dependency graph. The exposure path is what distinguishes them.
Build-time compromise versus library vulnerability: different reachability models
It is worth distinguishing two classes of supply chain risk that have different reachability models.
Library vulnerabilities: a specific version of a library has a security flaw in its code. The attacker exploits it by sending specific inputs that trigger the vulnerable path. This is the standard reachability analysis case: identify whether attacker-controlled inputs can traverse the call graph to reach the vulnerable function.
Build-time or distribution compromise: the library artifact itself has been tampered with at the package registry or build system level. The attacker inserted malicious code that runs when the library is loaded or when certain APIs are called. This is a fundamentally different threat model. The code is not running because you explicitly called a function; it may run on import, on any call to the library, or on a specific trigger condition. Standard call-graph reachability analysis does not model this class of threat well, because the attack surface is the library's initialization code and side effects, not a specific vulnerable API.
We are not going to claim reachability analysis covers the second class. For compromised build artifacts, the response is artifact integrity verification (checking package signatures and checksums), software supply chain provenance (SLSA attestations, reproducible builds), and rapid detection of unexpected outbound network calls or file system modifications. Reachability analysis addresses the first class: library vulnerabilities in code that exists in declared form, where the risk depends on invocation paths.
SBOM as the prerequisite, not the answer
An SBOM is the inventory layer. It tells you what is in the application artifact. It is a necessary input to both compliance documentation and vulnerability matching. It does not itself tell you whether any of those components are on an exposure path.
The SBOM-to-reachability pipeline looks like this: the SBOM provides the complete package inventory; CVE matching against the SBOM produces the set of packages with known vulnerabilities; reachability analysis filters that set to the packages whose vulnerable functionality is on a path from an external entry point in the deployed topology. The output of the full pipeline is the set of packages where a patched version or a mitigating control is needed urgently, because the vulnerable code is reachable.
Stopping at the SBOM-to-CVE step and treating the entire matched set as equally urgent is the equivalent of treating all 847 scanner findings as equally urgent. The SBOM and CVE matching are correct inputs. The reachability filter is what makes the output actionable.
Practical implications for how you handle a new critical CVE in a popular library
A critical CVE drops for a widely-used HTTP client library. Half your services use it. The standard response: scope all services that have the library in their dependency closure, create remediation tickets for all of them, prioritize by environment (production first), and track patch deployment. This is correct and necessary as a completeness response.
The reachability layer adds differentiation within that set. Some of those services use the HTTP client in code paths that are only invoked by internal service-to-service calls, authenticated and from known-internal IP ranges. Some use it in code paths that handle external user requests. The vulnerability may require attacker-controlled HTTP response data (a server-side request forgery vector) or attacker-controlled outgoing request parameters. Depending on the specifics, exposure varies significantly across the services that share the same library version.
The reachability analysis cannot replace the patch work. All affected services should be patched. But the reachability analysis answers: which of these services needs emergency change management today, versus which can go through the standard patch cycle next sprint? Emergency change management for every affected service is expensive and creates its own risks through rushed deployments. Proportionate response, calibrated by actual exposure in each service's specific topology, is operationally better. Reachability gives you the data to make that call.
See reachability analysis on your own code
Connect your repositories and apply a reachability filter to your existing scanner findings. No configuration changes to your current toolchain required.
Request early access