DEV Community

Eldor Zufarov
Eldor Zufarov

Posted on • Edited on

The Attacker Lives Between Your Tools

Why your SAST, DAST, and SCA each see a clean report — and you still get breached


Every tool passed.

The SAST scan completed without critical findings. The SCA report showed no exploitable CVEs in production dependencies. The DAST run flagged three medium-severity issues, all triaged and accepted. The security dashboard was green. The compliance checkbox was ticked.

Then the breach happened anyway.

Not through a vulnerability any of the tools were looking for. Through the space between them.


The Architecture of Blindness

The modern application security stack was not designed as a system. It was assembled as a collection of independent instruments, each optimized for a specific layer, each reporting findings in isolation, each defining its own perimeter — and stopping at the edge of it.

SAST analyzes source code before it runs. It sees what developers wrote. It does not see what the application becomes at runtime — how components interact under load, how configuration transforms behavior, how infrastructure shapes the attack surface of code that looked clean in review.

DAST tests a running application from the outside. It sees how the application responds to crafted inputs. It does not see the source code that produced those responses, the dependency chain that assembled the runtime, or the infrastructure layer that routes requests before they reach the application.

SCA catalogs third-party components and maps them against known vulnerability databases. It sees what libraries are present. It does not see whether the vulnerable function in a flagged library is actually reachable from the application's execution path — which is why the average SCA report generates enough noise that teams learn to filter it rather than act on it.

Each instrument is technically accurate within its domain. The problem is that attackers do not operate within domains. They operate in the space between them — the gaps that no single tool owns, the transitions that no single tool watches, the moments where one layer hands off to another and assumes the other layer has checked what it needs to check.

That assumption is the attack surface.


Five Dead Zones

The gaps are not theoretical. They are structural properties of how the tools are built. Understanding them precisely is the first step to building coverage that does not stop at instrument boundaries.

Dead Zone 1: The Source-to-Runtime Gap

A developer writes a function that handles file uploads. SAST analyzes it, finds no injection flaws, reports it clean. The function is deployed. At runtime, the application runs inside a container with a misconfigured temporary directory mounted world-writable. The clean function, in a misconfigured environment, becomes an arbitrary file write primitive.

SAST saw clean code. It will always see clean code, because the code is, in isolation, clean. The vulnerability does not exist in the source. It exists in the combination of the source and the environment it runs in — and SAST's entire model of analysis ends at the boundary of the source.

DAST might catch the resulting behavior — but only if it is pointed at the right endpoint with a payload that exercises this specific path, which requires knowing the path exists in the first place. The 2025 Verizon DBIR found vulnerability exploitation rose 34% as an initial access vector, now rivaling phishing as a primary entry method. A meaningful share of those exploited conditions were not undisclosed zero-days — they were known weaknesses sitting exactly at this boundary, where a tool that checks code cannot see environment, and a tool that checks environment was never told what the code does with it.

Dead Zone 2: The Dependency Reachability Gap

SCA reports a critical CVE in a logging library. The security team triages it: the vulnerable deserialization function exists in the library, but — based on a manual review of the codebase — it does not appear to be called. The finding is accepted as low priority. The patch is deferred.

What the manual review missed: a middleware component added three sprints ago calls the logging library's initialization routine, which under specific error conditions invokes the deserialization path. The call chain is four hops long and only activates on malformed input that the application receives from a specific API endpoint.

The attacker does not need to read the code. He needs to send the right malformed input to the right endpoint. The reachability was always there. The SCA tool reported the CVE. Nobody traced the path.

This gap is systemic. The OWASP Top 10 2025 ranks Software Supply Chain Failures at number three. The Verizon 2025 DBIR puts third-party involvement in breaches at around 30% and rising. Both data points reflect the same structural problem: teams know their dependencies have vulnerabilities. They do not know which ones are actually reachable from their specific execution context. The tools report presence. They do not report exposure.

Dead Zone 3: The Configuration Inheritance Gap

DAST tests the application in the staging environment. Staging is configured to mirror production, but with one difference the team made six months ago and has since forgotten: a Content Security Policy header that blocks inline script execution in production is relaxed in staging to simplify debugging. The DAST scan runs clean against staging, because in staging there is nothing to bypass. The production application — the one users actually reach — has a CSP gap that no scan has ever pointed at.

Unlike Dead Zone 1, where the gap is between code and the environment it runs in, this gap is between two environments that are assumed to be equivalent and are not. Nothing in the standard stack owns the question "does what we tested match what we shipped?"

The Blue Shield of California breach, disclosed in April 2025, shows how far this gap can extend when nobody is assigned to it. Between April 2021 and January 2024 — nearly three years — a Google Analytics configuration on Blue Shield's member portal transmitted protected health information for roughly 4.7 million members to Google's advertising platform. The company described it as the result of a website misconfiguration. No application vulnerability. No exploit. A configuration setting, present in production, that none of SAST, DAST, or SCA were ever positioned to evaluate — because none of them treat third-party tracking configuration as part of the security surface at all.

Dead Zone 4: The Patch Window Gap

In April 2025, a critical zero-day in SAP NetWeaver — CVE-2025-31324, an unauthenticated file upload flaw in the Visual Composer component, CVSS score 10.0 — was found being actively exploited in the wild before SAP had even confirmed it as a vulnerability. Researchers at ReliaQuest traced exploitation activity back to late March. By the time SAP issued an out-of-band emergency patch, the Shadowserver Foundation counted roughly 450 internet-facing instances still vulnerable, and attackers had already deployed JSP web shells to multiple compromised environments — establishing persistent access that the patch itself would not remove.

No SAST, DAST, or SCA tool in any of those organizations failed here. None of them are designed to know about a vulnerability before the vendor discloses it. The gap is not in detection. It is in the time between "a patch exists" and "the patch is applied, verified, and any pre-patch compromise is checked for" — and during that window, which for many organizations runs into weeks once change management, testing, and scheduling are factored in, the system is exposed regardless of what the scanners report, because the scanners are evaluating a version of the system that no longer matches reality.

This is the gap that turns "we have a patch" into a false sense of resolution. Applying the patch closes the vulnerability. It does not remove a web shell that was planted three weeks before the patch existed — and nothing in the standard stack checks for that, because checking for the consequences of a gap is a different task than checking for the gap itself.

Dead Zone 5: The Inter-Tool Correlation Gap

SAST flags an input validation issue in a data processing service — medium severity, accepted with a note to fix in the next sprint. SCA flags an outdated XML parsing library in the same service — low severity, the vulnerable function appears unused. DAST, running against a different endpoint of the same service, flags an information disclosure issue in error responses — low severity, no sensitive data visible in the test payload.

Three findings. Three separate reports. Three separate triage decisions. No single analyst sees all three in context.

An attacker sees the combination: unvalidated input, reaching an XML parser with a known deserialization flaw, in a service that leaks error details about its internal processing. Each finding individually is noise. Together they are an exploit chain. The SAST tool does not talk to the SCA tool. The SCA tool does not know what DAST found. The analyst who triaged the SAST finding has never seen the DAST report.

This is the pattern that a 2025 review of major breaches kept landing on: security responsibilities split across separate tools — patching here, endpoint protection there, identity management somewhere else — leave gaps that nobody is specifically watching, and those gaps are exactly where attackers operate with the most consistency. The blindness is not in any instrument. It is in the absence of a layer that reads all the instruments together.


Why the Standard Response Fails

The industry's answer to the inter-tool gap is, predictably, more tools.

Add an IAST agent to the runtime. Add a CSPM scanner for cloud configuration. Add an API security gateway. Add an ASPM platform to correlate findings across sources.

Each addition extends coverage in one dimension. Each addition also adds another boundary, another handoff, another assumption that the adjacent layer has checked what it needs to check. The stack grows. The dead zones migrate. The architecture of blindness is preserved at a higher level of complexity.

The more fundamental issue is that tool-centric security measures attack surfaces as a collection of domains, each with its own scanner, each reporting independently. The attacker does not see domains. He sees a system. He maps the transitions between layers because he knows that is where the assumptions live — and assumptions are not checked by any scanner.

Teams routinely defer or accept findings not because they are careless, but because every tool reports in isolation and every finding competes for the same remediation backlog without context on which findings, combined, actually matter. When the signal that determines real risk — the chain, not the individual finding — never reaches anyone, deferring individual findings is a locally rational response to a system that does not surface the global picture.


What Coverage Without Dead Zones Requires

Closing the gaps does not require more tools. It requires a different organizing principle.

Coverage must be defined by attack paths, not by tool domains. The question is not "does SAST cover this code path" or "does DAST test this endpoint." The question is: "can an attacker reach a sensitive operation by chaining findings from different tool domains?" If the answer to that question cannot be determined from the tooling in place, the coverage is incomplete regardless of how many tools are running.

This means attack path analysis cannot be reconstructed after the fact from individual tool reports. It has to be built into the analysis layer — a layer that ingests findings from SAST, DAST, SCA, infrastructure scanners, and configuration baselines simultaneously and looks for combinations that create reachable exploit chains, not just individual findings that exceed a severity threshold.

The patch window gap requires a different operational model than the vulnerability detection gap. Detection is a tooling problem. Remediation velocity is an organizational problem. As the SAP NetWeaver case shows, even an emergency patch released within days of disclosure does not close the exposure window retroactively — it stops new exploitation while leaving open the separate question of whether exploitation already happened during the window before the patch existed. Closing this gap means tracking "what is vulnerable," "what is exploitable right now given current configuration," and "what may already have been exploited during the exposure window" as three separate questions, each with its own urgency.

A vulnerability that exists in a library but is unreachable from any production execution path is a different risk than a vulnerability in a component that handles unauthenticated external input. The tools that report both as "critical" are not wrong. They are solving the wrong problem. The operational question is not "what is the CVSS score" but "what is the blast radius if this fires in production, given what I know about the call graph, the configuration, and the network topology."

Configuration must be treated as part of the attack surface, not as a precondition to security testing. The Blue Shield breach did not require a vulnerability at all — a configuration setting, unmonitored for nearly three years, was the entire incident. Configuration divergence between environments, missing security headers in production but not in staging, overpermissioned service accounts that DAST never touches — these are first-class attack surface elements that require first-class coverage, not afterthoughts left to whichever tool happens to have a checkbox for them.


The Structural Observation

Every dead zone in the standard security stack shares the same root cause: each tool owns its domain and assumes the adjacent tool owns its own domain, and nobody owns the boundary between them.

This is not a technology problem. It is an architectural problem — the same architectural problem that produces the alert-list-to-exploit-graph gap in runtime security, the same problem that produces compliance theater in awareness training. The instruments are optimized for their individual functions. The system has no function that is responsible for the space between instruments.

The attacker's advantage in both cases — Blue Shield and SAP NetWeaver — was not sophistication. In neither case did the attacker need to defeat a SAST scan, evade a DAST crawler, or find an unreachable CVE. One found a configuration nobody was watching. The other found a window between disclosure and remediation that no scanner is designed to close. Both were, in the language of the standard stack, "not a finding" — right up until they were the entire incident.

That soft spot is always in a dead zone.

The question is not whether your tools are good. They probably are, within their domains.

The question is who is responsible for the space between them — and whether that responsibility has a tool, a process, and an owner, or whether it is the one thing on the security team's map that is simply marked assumed covered.

The attacker has already checked whether that assumption is correct.

He is counting on the fact that you have not.

Top comments (0)