What You Should Know About Dependency Reachability in SCA

Understand dependency, function-level, and dataflow reachability for accurate supply chain results.

December 15th, 2025
Share

If you've ever been buried in vulnerability alerts from a Software Composition Analysis (SCA) tool, you're not alone. Many security and development teams today face the same problem: a sea of alerts, most of which have little to no impact on the actual security of the application.

This alert fatigue isn’t just annoying, it’s costly. It leads to wasted triage effort, slower patch cycles, and increasing friction between developers and security teams. The root of the problem lies in a basic limitation of traditional SCA tools: they treat every known vulnerability in every dependency as equally important, without knowing whether your code even uses the affected part of the library.

Reachability analysis was introduced to solve that problem. But not all reachability is created equal. 

  • Dependency reachability: Is the package used at all? 

  • Function-level reachability: Is the vulnerable function called? 

  • Dataflow reachability: Is untrusted or risky data flowing into that call? 

Those distinctions may not always be clear, so we’ll explore them more carefully in this post. We’ll break down what reachability really means in an SCA context, explore the different levels of reachability analysis used in modern tools, and explain why some approaches give much more accurate and useful results than others. 

What Is Reachability Analysis in SCA?

Reachability analysis in Software Composition Analysis (SCA) is the process of determining whether a known vulnerable function in a third-party package is actually used — or reachable — by the application code. If a vulnerability cannot be reached through the application’s execution paths, it's much less likely to be exploitable.

Most SCA tools identify known vulnerabilities in third-party packages by checking the version numbers listed in manifest files (like package.json or requirements.txt). But they stop there. They don’t look at whether the vulnerable part of that package is ever actually used.

This is where reachability analysis comes in. Instead of assuming every vulnerability is relevant, reachability tries to determine which ones are reachable from your code. It isn’t exploitable if it isn’t used. This dramatically reduces the number of alerts that need attention and helps teams focus time on other risk factors and spend more time shipping the features that their customers care about. 

But there are multiple types of reachability analysis, each with different capabilities and limitations.

Three Types of Reachability You Need to Know

Reachability analysis exists on a spectrum — from basic dependency checks to deep static analysis. Here are the three key types:

1. Dependency Reachability

This is the most basic form of reachability. It checks whether your application imports a vulnerable package at all.

If a package is listed in your dependencies but never imported, it’s clearly not reachable and the associated vulnerability can usually be safely ignored.

But that’s where the insight stops. Dependency-level reachability can’t tell you if the vulnerable part of the package is ever used, or how. You might import a package and only use its safe functions, but this analysis would still flag it as “reachable.”

Think of it as checking whether a book is on your shelf, not whether you actually opened it, let alone read the dangerous chapter. Exploitability can be related to installation hooks or initialization issues, but that’s an edge case.

2. Function-Level Reachability

This is a more advanced approach. Function-level reachability analyzes your application code to see if any known vulnerable functions are actually called.

This means it can distinguish between importing a package and actively using the specific function that contains the vulnerability. As a result, it screens out far more false positives than dependency-level analysis.

However, function-level analysis still can’t assess how the vulnerable function is being used. In many real-world cases, your code might call a vulnerable function in a way that isn’t actually risky. For example, by passing only static inputs there isn’t really a chance for an attacker to introduce unexpected results.

That’s where the next level of reachability becomes critical though.

3. Dataflow Reachability

Dataflow reachability adds a deeper layer of insight by looking at how data flows through your code into the vulnerable function.

This lets the analysis determine whether the way your application calls a vulnerable function could actually lead to an exploit. For example, if untrusted user input flows into a SQL query function known to be vulnerable, that’s a real risk. But if the function is only ever called with hardcoded values, the risk is negligible.

Semgrep Supply Chain, for example, uses dataflow reachability to differentiate between reachable-but-safe and reachable-and-exploitable paths. This helps eliminate many of those false positives that even function-level analysis would report and burn into productive time.

Reachability in Practical Terms

The idea behind reachability isn’t academic. In real-world software development, the difference between seeing 100 vulnerability alerts versus 5 actionable ones can determine whether a fix happens this week or gets buried in a backlog. It’s far easier to wash one dirty plate than it is to motivate yourself to go through an entire sink of dirty dishes.

A good reachability-based SCA tool can help:

  • Avoid unnecessary updates for packages that aren’t used

  • Focus remediation efforts on real, exploitable issues

  • Minimize alert fatigue and security-developer friction

  • Build trust in the tooling and make it more likely to be adopted (getting value for the investment)

Some vendors advertise function-level reachability but only offer it during full scans that are too slow for day-to-day use or only available for specific programming languages. Others may use dependency-level reachability as a “fast scan” alternative which brings back all the noise you were looking to avoid.

What are Malicious Dependencies?

A reachability classification like malicious dependencies indicates a finding that the use of a dangerous package, or dangerous version of a package, that is designed to compromise systems. These packages are inherently dangerous, and thus need to be immediately updated.

Many of the recent security research alerts such as S1ngularity, Sha1-Hulud, etc. fall into this category that simply having the specific compromised packages is detrimental to the security of the code base.

Take the Next Step: Read the Full Whitepaper

If you want a deeper understanding of how dependency-level, function-level, and dataflow reachability each impact scan speed, noisy results, and exploitability decisions, take a look at our full whitepaper:

Reachability Analysis: Cutting Through Noise to Identify the Risks That Actually Matter

Inside, you’ll find:

  • Side-by-side comparisons of reachability types

  • Examples of how reachability analysis identifies (or misses) real risks

  • Insights into how Semgrep uses static analysis to go beyond just function calls

  • Performance benchmarks and implementation considerations

This whitepaper is especially useful for security engineers, AppSec teams, and developers evaluating code-aware SCA solutions that prioritize actual exploitability over package-level noise.

Whether you're evaluating SCA tools or just trying to understand what “reachability” really means in your security pipeline, this guide will help you cut through the noise — and focus on what really matters.


About

semgrep logo

Semgrep enables teams to use industry-leading AI-assisted static application security testing (SAST), supply chain dependency scanning (SCA), and secrets detection. The Semgrep AppSec Platform is built for teams that struggle with noise by helping development teams apply secure coding practices.