Technical

Reachability Analysis: Cutting Through CVE Noise to Find What Actually Matters

Why most CVEs in your dependency tree are not exploitable in your application, and how reachability analysis separates real risk from noise.

Nayan Dey
Security Researcher
8 min read

The average enterprise application has hundreds of dependencies. Those dependencies collectively contain dozens — sometimes hundreds — of known CVEs. Security teams are expected to triage, prioritize, and remediate every one of them. And the dirty secret of vulnerability management is that the vast majority of those CVEs pose zero actual risk to the application.

A CVE exists in a dependency. The dependency is included in the application. But the vulnerable function is never called. The vulnerable code path is never exercised. The conditions required for exploitation do not exist in the application's runtime context. The CVE is real, the risk is not.

This is the problem reachability analysis solves. And it is rapidly becoming the most important capability in modern vulnerability management.

The Noise Problem

To understand why reachability analysis matters, you need to understand the scale of the noise problem.

A typical Node.js application has 500-1500 dependencies when you include the full transitive tree. A Java application built with Spring Boot often exceeds 300 direct and transitive dependencies. A Python application with a machine learning stack can easily pull in 200 or more packages.

Run a vulnerability scanner against any of these dependency trees and you will get a list of CVEs that ranges from a handful to several hundred. Security teams are then expected to assess each one, determine its severity in context, and decide on remediation — update the dependency, apply a workaround, or accept the risk.

At scale, this is impossible to do manually. The result is one of two failure modes:

Alert fatigue. Teams receive so many CVE notifications that they stop paying attention. Critical vulnerabilities get lost in the noise alongside low-severity issues in unused code paths. This is the more dangerous failure mode — it means genuinely exploitable vulnerabilities are being deprioritized because they are buried in a list of hundreds of findings that all look the same.

False urgency. Teams treat every CVE as equally urgent, burning remediation capacity on vulnerabilities that cannot be exploited in their specific context. Engineering time is finite. Every hour spent updating a dependency for a non-exploitable CVE is an hour not spent on a vulnerability that actually matters.

What Reachability Analysis Actually Does

Reachability analysis determines whether the vulnerable code in a dependency is actually reachable from your application's code. If your application never calls the vulnerable function, never exercises the vulnerable code path, or never creates the conditions that make the vulnerability exploitable, the CVE is not reachable and its effective risk to your application is negligible.

There are two primary approaches:

Static Reachability Analysis

Static analysis examines the application's code and dependency graph without executing the application. It builds a call graph that maps which functions call which other functions, and then checks whether any call path leads from the application's code to the vulnerable function in the dependency.

The process works roughly like this:

  1. Identify the vulnerable function(s) associated with a CVE — the specific method, class, or module that contains the flaw.
  2. Build a call graph from the application's entry points (API handlers, main functions, event listeners) through all dependencies.
  3. Determine whether any path in the call graph reaches the vulnerable function.
  4. If no path exists, the CVE is marked as unreachable.

Static analysis is fast and can be run during CI/CD without executing the application. Its limitation is that it tends to over-approximate — it identifies potential call paths based on what the code could do, not what it actually does at runtime. This means some CVEs are marked as reachable when they are technically reachable in theory but never exercised in practice.

Dynamic Reachability Analysis

Dynamic analysis monitors the application during execution (typically in a test or staging environment) and records which functions and code paths are actually exercised. If a vulnerable function is never called during normal operation, it is marked as unreachable.

Dynamic analysis is more precise than static analysis because it measures actual behavior rather than theoretical possibility. Its limitations are coverage-dependent — if your test suite does not exercise a code path, dynamic analysis cannot tell you whether it is reachable in production. It also requires a running application, which makes it slower and more complex than static approaches.

Hybrid Approaches

The most effective reachability analysis combines both methods. Static analysis provides broad coverage and fast results. Dynamic analysis adds precision for the cases where static analysis is uncertain. The combination typically reduces false positives (CVEs marked as reachable that are not) to below 5%, while maintaining low false negatives (CVEs marked as unreachable that actually are).

The Impact on Vulnerability Management

Organizations that implement reachability analysis consistently report that 70-90% of CVEs in their dependency trees are not reachable. This is not a hopeful estimate — it is a measured outcome across multiple independent studies and vendor reports.

The implications for vulnerability management are significant:

Reduced triage burden. Instead of evaluating 200 CVEs, the security team evaluates 20-60. The remaining findings are deprioritized automatically based on reachability status. This makes manual triage feasible even for large dependency trees.

Faster remediation of real risks. When the noise is removed, the remaining findings are the ones that actually matter. Teams can focus remediation effort on genuinely exploitable vulnerabilities, which reduces mean-time-to-remediation for the CVEs that count.

Better engineering relationships. One of the biggest sources of friction between security and engineering teams is the perception that security generates false alarms. When every vulnerability finding comes with a reachability assessment, engineering teams trust the findings more and are more willing to prioritize remediation.

More accurate risk reporting. Reporting "we have 200 CVEs in our dependency tree" creates a misleading picture of risk. Reporting "we have 200 CVEs, of which 30 are reachable and 5 are in critical code paths" gives leadership a much more useful understanding of actual exposure.

Limitations and Honest Caveats

Reachability analysis is powerful but not perfect. Understanding its limitations is important for using it effectively.

Not all CVEs have precise vulnerable function data. Reachability analysis depends on knowing which specific function or code path is vulnerable. For well-documented CVEs in popular libraries, this information is available. For less common packages or vaguely described vulnerabilities, the analysis may not be possible.

Reachability is not exploitability. A reachable vulnerability is not necessarily exploitable. Exploitation depends on additional factors — input validation, authentication requirements, network exposure, runtime environment — that reachability analysis does not fully assess. Reachability narrows the field; it does not replace contextual risk assessment.

Call graph construction has limits. Dynamic dispatch, reflection, dependency injection, and other runtime behaviors can make static call graphs incomplete. Languages like Java and Python, which rely heavily on these patterns, present more challenges for static reachability analysis than languages like Go or Rust.

Coverage matters for dynamic analysis. Dynamic reachability is only as good as the code paths exercised during monitoring. Low test coverage means low confidence in dynamic results. Organizations with mature test suites get more value from dynamic analysis.

Getting Started With Reachability Analysis

Prerequisites

Before implementing reachability analysis, ensure you have:

  1. Comprehensive SBOMs for your applications, including transitive dependencies with exact version numbers
  2. A vulnerability database that maps CVEs to specific vulnerable functions (not just package versions)
  3. Build artifacts or source access that enable call graph construction

Integration Points

Reachability analysis adds the most value at two points in the development lifecycle:

During CI/CD. Run static reachability analysis as part of vulnerability scanning in your build pipeline. This adds a reachability status to each CVE finding, allowing policy gates to differentiate between reachable and unreachable vulnerabilities.

During triage. When security teams review vulnerability findings, reachability status should be a primary sorting criterion. Reachable CVEs get immediate attention. Unreachable CVEs go into a monitoring queue.

Setting Policy

Organizations need to decide how reachability status affects their vulnerability management policies:

  • Reachable + Critical/High severity — remediate within SLA (typically 7-30 days)
  • Reachable + Medium/Low severity — remediate within extended SLA or next release cycle
  • Unreachable + Critical/High severity — monitor for reachability changes, remediate opportunistically
  • Unreachable + Low severity — accept risk, review periodically

The key principle is that reachability informs priority, but it does not eliminate the vulnerability. An unreachable CVE today could become reachable tomorrow if the application's code changes. Continuous monitoring is essential.

How Safeguard.sh Helps

Safeguard's reachability analysis engine integrates directly with our SBOM and vulnerability correlation pipeline. When a CVE is identified in your dependency tree, Safeguard automatically performs static reachability analysis to determine whether the vulnerable code path is exercised by your application. Findings are annotated with reachability status — reachable, unreachable, or indeterminate — and policy gates can enforce different remediation SLAs based on reachability. Griffin AI lets security teams query reachability across their entire portfolio: "show me all reachable critical CVEs in production services." The result is a vulnerability management program focused on the findings that actually represent risk, not the ones that just happen to exist in your dependency tree.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.