Static analysis reads your code. Dynamic analysis attacks your running app. You need both.
| SAST | DAST | |
|---|---|---|
| Full name | Static Application Security Testing | Dynamic Application Security Testing |
| Analyzes | Source code, bytecode, or binaries | Running application via HTTP |
| When in SDLC | During development (shift left) | After deployment or in staging |
| Access needed | Source code | Just a URL |
| Finds well | Hardcoded secrets, injection sinks, insecure functions | Misconfigurations, auth flaws, runtime behavior |
| Misses | Runtime issues, business logic, auth flows | Code-level flaws it can't reach via HTTP |
| False positives | High — flags code paths that may never execute | Lower — it tests real behavior |
| Speed | Fast — runs in CI in minutes | Slow — crawls and tests every endpoint |
| Examples | Semgrep, CodeQL, Bandit, SonarQube | Burp Suite, OWASP ZAP, Nuclei |
SAST catches things DAST can't see — a dangerous eval() buried in a code path that's hard to reach via HTTP, or a hardcoded API key that never appears in any response. DAST catches things SAST can't reason about — broken authentication flows, missing security headers, and runtime misconfigurations.
If I had to pick one, I'd start with SAST in CI (Semgrep is free and fast) because it catches issues before they ship. Add DAST in staging once you have the basics covered. Most teams that claim to do both are actually running SAST in CI and ignoring the alerts.
Business logic flaws. Neither tool understands that "a user shouldn't be able to apply the same coupon twice" or "this API should only return data for the authenticated user's organization." That's where manual testing, code review, and bug bounty programs fill the gap.