Skip to content
Back to Quality Assurance

Dynamic Analysis (DAST)

Scan the running application from the outside, probing for vulnerabilities a black-box attacker would find.

Why

SAST sees the code but not the runtime configuration; DAST sees the running app but not the source. They are complementary. DAST finds the vulnerabilities that only manifest at runtime: a misconfigured security header, a session cookie without HttpOnly, an endpoint that returns 200 when it should return 401, an SSRF that works because the production firewall allows an egress that staging did not. It probes the app exactly as an attacker would — no source access, no inside knowledge — so it validates that the controls you think are in place actually work when the app is running. It is the most realistic test of your production security posture, short of a human pen test.

When

Run a DAST scan on every deploy to staging (automated, ZAP baseline) and a deeper scan weekly or pre-release (ZAP full scan, Nuclei). Do not run against production without coordination — active scans can break things.

How

1. Choose a DAST tool
   - OWASP ZAP (free, industry standard, good API + automation)
   - Nuclei (fast, template-based, good for known CVEs and misconfig)
   - Commercial: Burp Suite, Acunetix, Netsparker (deeper, pricier)

2. Run a baseline scan on every staging deploy (passive, <2 min)
   - ZAP baseline: spiders the app, records requests, flags passive findings
   - No active probing — safe to run on every deploy, catches headers/cookie/config issues
   - Fail the deploy on new high-severity findings

3. Run a full active scan weekly or pre-release (10-30 min)
   - ZAP active scan: sends attack payloads (SQLi, XSS, path traversal) to every form/param
   - Run against a dedicated staging instance, not prod — active scans can crash the app
   - Triage findings: true positive → fix; false positive → suppress with reason

4. Authenticate the scanner for areas behind login
   - Provide ZAP a login macro/script so it can reach authenticated endpoints
   - Without auth, the scan misses 80% of the app (everything behind the login wall)

5. Integrate findings into your tracker and trend them
   - Open a ticket for each true positive; track time-to-fix
   - Compare scan-to-scan: new findings are regressions, resolved findings are wins
   - Feed the DAST report into your OWASP controls matrix as evidence

Example

# Run ZAP baseline scan on staging after every deploy
# scripts/dast-baseline.sh
#!/bin/bash
TARGET="https://staging.example.com"
docker run -t ghcr.io/zaproxy/zaproxy:latest   zap-baseline.py -t "$TARGET" -J zap-report.json -r zap-report.html   --hook=/zap/custom_hook.py
# Exits non-zero on high-severity findings → fails the deploy pipeline.

# GitHub Actions: DAST on staging deploy
# .github/workflows/dast.yml
name: DAST
on: [workflow_dispatch]  # triggered after staging deploy
jobs:
  zap-baseline:
    runs-on: ubuntu-latest
    steps:
      - uses: zaproxy/[email protected]
        with:
          target: "https://staging.example.com"
          cmd_options: "-a -j"
          # -a: active scan, -j: JSON output
          # Fail if HIGH or CRITICAL findings. WARNINGS are posted but do not fail.

# Sample finding:
#  ❌ High: Cross Site Scripting (Reflected) at /search?q=
#    Attack: <script>alert(1)</script>
#    Evidence: the search term is reflected unescaped in the response.
#    Fix: escape user input before rendering, or use a CSP with script-src 'none'.

Common Problems

  • ⚠Running an active DAST scan against production without coordination — the scan sends attack payloads that can crash the app, corrupt data (a successful SQL injection in a POST), or trigger rate limits and WAF blocks that take the site down.
  • ⚠Running only unauthenticated scans misses everything behind the login wall — the most sensitive endpoints (account settings, payment, admin) are never tested, and the DAST report gives false confidence.
  • ⚠Treating every DAST finding as a critical bug to fix immediately — many are low-severity (missing a security header) or false positives (a reflected parameter that is actually sanitized), and the team burns out triaging noise.
  • ⚠Running DAST only once at launch and never again — new endpoints added after launch are never scanned, and a regression in an existing endpoint (a refactor that removed input validation) goes undetected.

Best Practices

  • ✓Run a passive baseline scan on every staging deploy (safe, fast, catches config/header issues) and an active scan on a dedicated staging instance weekly — never run active scans against production.
  • ✓Authenticate the scanner with a test account so it can reach the sensitive endpoints behind login — 80% of the attack surface is authenticated, and an unauthenticated scan is incomplete.
  • ✓Triage findings by severity and exploitability: fix high/critical immediately, schedule medium, and suppress low/false-positives with documented reasons — do not let noise drown the signal.
  • ✓Trend the finding count scan-over-scan and feed it into your security dashboard — a rising trend on a stable codebase means new endpoints are being added without security review.