Software Securityhome
Fix a findingSearch
Phase 4 · Testing

SAST and DAST

Static application security testing (SAST) reads source or compiled code without running it and flags risky data flows, such as request input reaching a SQL query. Dynamic testing (DAST) sends requests to a running application from outside and reports how it responds.

Each sees what the other cannot. A static rule can trace request.args into cursor.execute on a route no test reaches; a dynamic scan shows what the deployed build, with its real configuration, returns. Neither knows your authorization rules, and OWASP warns that SAST produces many false positives and rarely finds access control or configuration flaws, so a finding counts once a request reproduces it.

Who
Developers triage results for their own code; AppSec writes project rules and owns the scanner setup
When
Static rules on every pull request; dynamic scans against a test deployment of each release candidate, before it ships
How often
SAST on every change plus a full scan nightly; an authenticated DAST scan nightly or on each release candidate
You end up with
Results tied to a commit and a deployed digest, a reproducing test for each confirmed finding, and a reviewed list of suppressions

Do this

  1. Pick tools that understand your stack

    Choose a static analyzer that supports your languages and frameworks, such as Semgrep, CodeQL, Bandit or gosec, and a dynamic scanner such as ZAP. OWASP's selection criteria include language support, accuracy measured by false positive and false negative rates, and output in SARIF, the OASIS standard format for analysis results. Run SAST on pull requests as part of CI security checks.

  2. Write rules for your own sinks, with tests

    Default rules do not know your wrappers, such as an internal db.raw() helper. Add project rules for them, and keep each rule beside a test file annotated ruleid: where it must fire and ok: where it must not. Run semgrep --test (or your tool's equivalent) in CI, so a broken rule cannot silently report nothing.

  3. Scan a test deployment as a logged-in user

    Point the dynamic scanner at a test environment running the release candidate, with synthetic data and a dedicated account for each role. Configure authentication: ZAP's documentation warns that without it the scanner cannot reach any protected functionality. Exclude logout and destructive routes from the scan.

  4. Use passive scans in CI and active scans in test

    ZAP's baseline scan spiders for about a minute and only observes responses, so it is designed to run in CI, even against production. The full scan sends real attacks and can run for a long time: run it, or any active scan, only against a test environment you own and can reset.

  5. Prove the scan reached the protected pages

    Before trusting a clean result, find a 200 response from a protected page under the scanner's user in the scan log, and record the deployed artifact digest with the results. A scan whose session expired, or that only ever saw the login page, reports nothing because it tested nothing.

  6. Confirm each finding before fixing it

    Connect the static path from source to sink with a request against the deployed build that shows the effect, such as rows belonging to another owner. Turn that request into a failing test, fix the code, and close the finding only when the test passes on the new build and a normal request still works. Track it with an owner, as Fix a finding describes.

  7. Suppress one finding at a time, with a reason

    For a false positive, suppress that rule at that location, such as nosemgrep: <rule-id> on the line or a dismissal in code scanning, and record why the sink is safe. Never disable a whole rule or exclude a directory to reach zero. Review suppressions on a schedule: each needs a rule ID, a location, a reason and an owner.

Done when

Confirmed findings have a reproducing test, and suppressed false positives have a recorded reason.

Mark it in the gap check

Common mistakes

  • Trusting a clean DAST report from a scan that never logged in. It tested the login page, and every protected route went unscanned.
  • Running default rules untuned on every repository. Developers learn to dismiss the tool, and real findings are dismissed with the noise; OWASP SAMM's tuning level asks you to filter irrelevant and low-probability warnings.
  • Excluding directories or disabling rules to reach zero findings. The count falls because the scope shrank, not because the code got safer.
  • Scanning a stale environment. A clean scan of the build from last week says nothing about today's commit, so record the deployed digest with every result.
  • Reading a clean SAST and DAST run as proof of security. Neither knows your authorization rules or business logic, so cover those with abuse-case tests (Abuse cases) and review.
  • Pointing an active scan at production. It sends real attack payloads to live systems and real data.

SAST, DAST or IAST?

Each looks at a different representation of the same software, so each finds different bugs. A common order is SAST on pull requests first, then DAST against a test deployment.

SAST, DAST or IAST?: table
QuestionSASTDASTIAST
What it examinesSource or compiled code, without running itThe running application, over HTTP from outsideThe running application, from an agent inside it while tests run
Finds wellData flows from input to dangerous sinks: injection, XSS, unsafe deserialization, weak crypto callsRuntime behavior: missing headers and cookie flags, reflected XSS, some injection, TLS problemsVulnerable data flows observed during tests, with the request and stack that triggered them
MissesAuthorization and logic flaws, configuration, framework behavior its rules do not modelPages it cannot reach or log in to, logic flaws, the root cause in codeCode your tests never execute; unsupported runtimes
Where it runsEditor and pull request; full scan nightlyTest or staging deploymentTest environment, as an agent in the app
ExamplesSemgrep, CodeQL, Bandit, gosecZAP, NucleiMostly commercial agents for specific runtimes

Tools and guides

Standards

NIST SSDF 1.1
PW.7 Analyze Human-Readable Code to Identify Vulnerabilities and Verify Compliance with Security RequirementsPW.8 Test Executable Code to Identify Vulnerabilities and Verify Compliance with Security Requirements
OWASP SAMM 2
Security Testing

Sources

  1. OWASP: Source Code Analysis Tools
  2. OWASP: Vulnerability Scanning Tools
  3. ZAP: Authentication
  4. ZAP: Baseline scan
  5. ZAP: Full scan
  6. Semgrep: Test rules
  7. Semgrep: Ignore files, folders and code
  8. OASIS: Static Analysis Results Interchange Format (SARIF). Version 2.1.0 Plus Errata 01 (28 August 2023).
  9. OWASP SAMM: Security Testing, Scalable Baseline stream
  10. NIST SP 800-218: Secure Software Development Framework (SSDF) Version 1.1. February 2022.

Find your next answer

Type to search. Search runs in your browser.

Searches run in your browser, but the host can infer them from the index files they load. The address shows your search so you can bookmark or share it.