Application Security

Taint Analysis vs Reachability: What You Actually Need in 2026

Taint and reachability sound similar and answer different questions. Here is when each one matters, where vendors blur the line, and how to use both.

Karan Patel
Staff Engineer
6 min read

Taint analysis and reachability analysis are two different things that vendors increasingly market under overlapping labels, and the conflation is causing real confusion in procurement conversations. Both reduce SCA noise, both involve call graphs, and both produce more credible findings than a raw dependency scan. They answer different questions, though, and a program that buys one expecting the other ends up with a tool that does not match the workflow.

This post draws the technical line between them, walks through where each one wins, and explains how a mature AppSec program uses both. It is aimed at security architects evaluating SAST and SCA platforms and tired of marketing taglines that paper over real differences.

What does each one actually answer?

Reachability analysis answers the question: from a service's entry points, can the call graph reach the vulnerable function inside a third-party library? It works on a known CVE attached to a known function, and the analysis is whether your code calls that function transitively. The output is a yes-or-no per CVE, sometimes with the calling path attached. Reachability is fundamentally a structural question about code presence.

Taint analysis answers a different question: can attacker-controlled data flow from an entry point to a sensitive sink, possibly through arbitrary intermediate functions, in a way that triggers an unsafe operation? Taint is about data flow, not just call graph edges. A function can be reachable but never receive tainted data, in which case a SQL injection or SSRF risk does not exist in practice. Conversely, taint can flow through legitimately reachable code to a sensitive sink, which is the actual exploitability question. Reachability is a precondition for taint analysis to matter, but it is not sufficient on its own.

When does reachability give you the right answer?

Reachability is the right primitive for SCA, the case where you have a known CVE in a dependency and need to know if your service is exposed. The CVE tells you which library function is vulnerable, the reachability engine tells you whether your code calls it, and the answer is either yes-patch-it or no-defer. This is the workflow that has compressed CVE alert volumes by 60 to 80% across the ecosystem and made reachable-only prioritization the default for serious AppSec teams.

Reachability also works for license compliance, where the question is whether a library with a restrictive license is actually used in production code. A GPL library present as a build-time-only dependency is a different risk than a GPL library linked into the production binary, and reachability draws that line. The same logic applies to FedRAMP allowlists and other compliance gates. Reachability is structural, fast, and decisive on the questions it can answer.

When do you actually need taint?

Taint is the right primitive for SAST and for first-party code review, where the vulnerability is not a known CVE but a potential issue in code you control. Examples include SQL injection in your own ORM usage, SSRF in your HTTP client calls, and XSS in your template rendering. Reachability tells you the dangerous function is called, which is not interesting because of course your code calls its own HTTP client. Taint tells you whether attacker input flows to that call in a way that could be exploited, which is the interesting question.

Modern SAST tools like CodeQL, Semgrep Pro, and Snyk Code all build taint engines as their core capability. They define source and sink patterns, propagate taint through assignments and function calls, and flag flows that connect a source to a sink without sanitization. The output is a list of code paths that an engineer can review and fix. This is fundamentally a different workflow than reading a CVE list, and the tools optimize for different things.

Where do vendors blur the line?

The blurring happens when a vendor claims their SCA tool does taint analysis on third-party code. This sounds compelling, and it is mostly marketing. Real taint analysis of third-party libraries is computationally expensive and produces low-signal results because the source-to-sink patterns inside a library are usually safe in isolation; the unsafe combination depends on how the library is called by your code. The interesting taint question is at the boundary between your code and the library, and reachability is the cheaper, more reliable way to answer it.

Some vendors do something they call "reachability with taint annotations" where they enrich reachability output with information about whether the calling code passes attacker-controlled data into the vulnerable function. This is genuinely useful for CVEs where the vulnerability requires hostile input, like injection or deserialization issues. CVE-2022-22965, the Spring4Shell issue, is a canonical example: reachability tells you the vulnerable binder is called, and the taint-aware version tells you whether you are binding from request bodies, which is the actual exploitability condition.

How should a mature program combine them?

Reachability runs on the SCA side, gating third-party CVE alerts to the reachable subset. Taint runs on the SAST side, finding first-party vulnerabilities in code you own. The two pipelines share infrastructure (call graphs, dataflow primitives) but produce different outputs for different audiences. Reachability output goes to the dependency upgrade triage; taint output goes to the application security review backlog.

The expensive thing to get right is the integration. A vulnerability that requires both an unpatched dependency (SCA) and a vulnerable code path that passes hostile input to it (SAST) is the highest-priority class. Tools that connect their reachability and taint engines and surface the joint findings are doing something genuinely valuable. Tools that run them in silos and produce two separate alert queues are leaving signal on the floor.

How Safeguard Helps

Safeguard runs reachability against every SBOM your CI produces, gating third-party CVE alerts to the subset your code actually calls. Griffin AI extends reachability with taint-aware enrichment for CVE classes that require hostile input, flagging the cases where both conditions are met and surfacing them as priority-one findings. Policy gates can enforce reachable-only blocking, taint-confirmed blocking, or both, depending on the risk tolerance of the gate. SBOM diffs, TPRM scoring, and zero-CVE base images sit underneath, so the foundation your services start from is clean and the analysis on top is meaningful.

Never miss an update

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