Scanning and Tools

SAST, DAST and SCA: What Each Scanner Type Can See

22 September 2026 9 min read

SAST, DAST and SCA all get filed under “application security testing,” but they don’t compete with each other. They answer three different questions about three different objects: what does the source code say, what does the running application do when attacked, and what components does the build depend on. A team that picks one and expects it to cover for the other two will eventually get burned by a bug class its chosen tool structurally cannot see.

The three evidence models: source code, running application, dependency manifest

Static Application Security Testing (SAST) reads source code, or in some tools an intermediate representation such as bytecode or an abstract syntax tree, without executing it. It builds a control flow graph and a data flow graph, then tracks tainted input from a source, a request parameter, a form field, a deserialized object, to a sink such as a SQL query, a shell command or a file path. Because it never runs the application, SAST needs no test environment, no credentials and no deployed instance. It also cannot tell you whether the vulnerable line is ever reached in production, or whether a network control in front of it makes exploitation moot.

Dynamic Application Security Testing (DAST) does the opposite. It has no access to source and, in most configurations, no awareness of the technology stack underneath. It crawls or replays traffic against a running instance, sends malformed or malicious payloads, and judges the result by the response: a status code, a timing difference, a reflected string, an error stack trace. DAST proves exploitability because it actually attempts to exploit the live target. Its blind spot is coverage: it can only test what it can reach, authenticate into and understand as a distinct page or endpoint.

Software Composition Analysis (SCA) does not look at your code at all. It reads manifest and lock files, package.json, requirements.txt, go.sum, pom.xml, a container image’s layer metadata, and matches the resulting component list against vulnerability databases such as the National Vulnerability Database, the GitHub Advisory Database or OSV. SCA answers a narrower question than the other two: which known, previously disclosed vulnerabilities exist in code you did not write. It cannot find a bug in your own logic, no matter how severe, because your own logic is not a dependency.

A single injection bug seen from all three angles, side by side

Take a login endpoint that concatenates a username parameter directly into a SQL string, on top of an ORM library with its own known CVE for a separate query-builder flaw.

SAST flags the concatenation itself: it traces the tainted username parameter from the HTTP handler to the string passed into the query execution call, and reports a line number in the source file, without ever sending a request. If the vulnerable pattern uses a dynamic query builder the tool’s ruleset doesn’t recognize, or the taint passes through a message queue or a cache before reaching the sink, the tool can lose the trail and miss the bug entirely.

DAST sends a payload, something like ‘ OR ‘1’=’1 or a boolean-based blind payload with a measurable time delay, at the live login endpoint, and confirms the injection by observing the actual response: a login bypass, a database error leaking table names, or a delay consistent with a sleep-based injection. It never sees the source line that caused the bug, and if the endpoint requires a session state or a multi-step form the crawler didn’t reconstruct, it never reaches the injection point at all.

SCA produces a completely separate finding: the ORM library is at version 4.2.1, and versions 4.2.1 through 4.2.6 carry a published CVE for an unrelated query-builder flaw. This has nothing to do with the developer’s own string concatenation bug. If a team runs only SCA, this specific injection stays invisible, because it lives in code the team wrote, not in a dependency with a CVE number.

None of the three tools, run alone, gives a complete picture of this one bug in this one application. That is the practical argument for running more than one class, not a sales pitch.

Signature strengths: what only SAST catches, what only DAST proves, what only SCA enumerates

SAST is the only one of the three that can find a vulnerability before the code ever runs anywhere: in a dead code path nobody has exercised in QA, in a hardcoded credential or API key, in a weak cryptographic primitive such as MD5 used for password hashing or a static initialization vector, or in a logic branch gated behind a feature flag that stays off in every test environment. It works equally well on a branch that has never been merged.

DAST is the only one of the three that confirms exploitability against the actual deployed stack, including issues that have nothing to do with application code: a missing security header, a verbose stack trace leaking a framework version, an admin path reachable without authentication, a misconfigured reverse proxy that strips an auth header, or a filtering rule that blocks one payload variant but not a close relative. None of that exists in source code; it exists in the deployed configuration, which only a tool that attacks the running system will ever observe.

SCA is the only one of the three that gives a full, versioned inventory of every third-party and transitive component in a build, including the dependencies of your dependencies that no developer on the team has read. It is also the only one where a finding can appear with zero code changes on your side: a CVE gets published against a library version you have used unmodified for two years, and yesterday’s clean build becomes today’s finding.

Typical false-positive and false-negative profiles of each class

SAST’s characteristic false positive is a sanitization pattern the tool doesn’t recognize: a framework’s built-in escaping, a validation library, or a custom wrapper around a parameterized query, all of which neutralize the taint in practice while the tool still flags the sink. Its characteristic false negative is taint crossing a boundary it doesn’t model: a value written to a queue, a cache or a temp file, then read back later and used in a sink. Tune this by maintaining a project-specific list of trusted sanitizers, and treat a finding that keeps reappearing after suppression as higher priority, not lower.

DAST’s characteristic false negative is anything it never reached: an API endpoint missing from its specification, a multi-step workflow its crawler didn’t complete, a parameter never fuzzed because it wasn’t in a visible form field, or a business logic flaw such as a price manipulation or an authorization bypass between two valid accounts, neither of which produces an obviously anomalous HTTP response. Its characteristic false positive is a payload that triggers an error page or a delay for reasons unrelated to real exploitability, such as a generic error handler firing on any malformed input. Authenticated, spec-driven scanning, feeding it an OpenAPI definition rather than relying purely on crawling, closes a large share of the negative side.

SCA’s characteristic false positive is a vulnerable function that exists in a dependency but is never called by your code, a reachability gap a manifest-only scan cannot see because it never inspects your call graph. Treat an SCA finding as urgent only once a reachability check confirms the vulnerable function is actually invoked; otherwise it belongs in a lower-priority patch cycle rather than an emergency one. Its characteristic false negative is a vulnerability not yet published to any database, or code that was vendored or copy-pasted rather than pulled through a package manager, since a manifest scan only sees what the manifest declares.

Where the three overlap and where the overlap is an illusion

Real overlap exists at one narrow point: a known-vulnerable library, SCA’s find, used at a call site where attacker-controlled input reaches it, SAST’s find, in a way that is actually exploitable from outside, DAST’s find. When all three line up on the same root cause, that is a strong, cross-validated signal worth escalating ahead of anything only one tool reported.

The illusion is assuming that running all three multiplies coverage the way adding lanes widens a highway. In practice each class looks at a different layer of the same system, and most findings from one class have no corresponding finding in the other two, because there is nothing for the other two to find at that layer. A closed-source third-party SaaS dependency has no source for SAST to read. An internal batch job with no HTTP interface has nothing for DAST to attack. A hand-rolled algorithm with zero third-party components has nothing for SCA to enumerate. Stacking three scanner classes on a codebase does not triple confidence in any single finding; it usually produces three separate report exports, in three separate formats, on three separate severity scales, describing three mostly non-overlapping sets of risk.

That is also where the operational cost shows up. The same underlying SQL injection can arrive as a SAST finding, a DAST finding, and, if the injection lives inside a vulnerable ORM version, a related SCA finding, each with its own identifier, its own severity number and its own remediation text. Platforms that ingest all three scanner classes, such as SITEY, correlate findings by asset, endpoint and weakness type rather than trusting each tool’s own label, so those three reports collapse into a single ticket with one status instead of three that drift out of sync during triage. The scanner integration layer is usually where that normalization has to happen before anything reaches a human queue, and the triage step is where duplicate or low-confidence findings from overlapping tools get filtered before they consume analyst time.

A simple decision table for which class to run at which point in the lifecycle

The lifecycle stage determines which class gives the best return for the compute and time it costs. Running DAST on every commit is slow and mostly redundant with what SAST already caught faster; skipping SCA at build time means a dependency with a two-year-old CVE ships unnoticed.

Stage Recommended class Why this stage fits this class
IDE or pre-commit SAST, incremental, changed files only Fast enough for a developer to wait on; catches the bug before it is committed
CI build SAST full scan plus SCA No running instance needed yet; can block a build on a critical injection pattern or a critical CVE
Staging or pre-release DAST, authenticated, spec-driven A real instance exists; this is the first point exploitability can be confirmed
Release gate SCA full SBOM plus DAST summary Final check for newly disclosed CVEs and unresolved dynamic findings
Production, ongoing SCA continuous plus periodic DAST plus reachability New CVEs get published against unchanged code; production configuration drifts from staging
After a patch ships Targeted retest, DAST or reachability re-check Confirms the specific finding is closed rather than trusting a patch command’s exit code

That last row is worth being strict about. A patch that installs cleanly and a service that restarts without error are not the same thing as a closed vulnerability. Platforms that automate this phase, such as SITEY, re-test the specific finding against the same proof of exploitability that opened it, rather than closing a ticket because a package manager reported success, and log the outcome against the original record in the vulnerability lifecycle. For teams reporting against ISO 27001, PCI DSS or SOC 2, that retest evidence is also what an auditor asks for when a control claims a vulnerability was remediated, which is why compliance mapping from a finding to a control matters as much as the finding itself.

None of this argues for buying the most expensive bundle available. It argues for matching the class to the question that actually needs answering at each stage: source-level reasoning early, real exploitability before release, and dependency awareness continuously, because that last one keeps changing without any commit from your team.

About SITEY

SITEY is an autonomous vulnerability management platform. It discovers, validates, prioritizes, remediates and re-tests vulnerabilities through an eight-phase automated pipeline, unifying output from 17 integrated scanners. SITEY is self-hosted: it runs in your own infrastructure and your findings are stored there. Outbound connections are limited to licence activation and the optional services you enable, such as an AI provider, CVE enrichment and patch catalogues. Pricing is 599 USD per month or 5,999 USD for a perpetual lifetime license. See pricing or how the platform works.

SITEY closes the loop, not just the report.Discover, validate, fix and verify in your own infrastructure.

See pricing