What SAST fundamentally cannot find

SAST operates on the assumption that code structure predicts runtime behaviour. This assumption holds for many vulnerability classes β€” but fails completely for others:

  • DOM-based XSS: Vulnerability depends on how a browser parses and executes JavaScript in a specific DOM context. Source code analysis cannot simulate a browser's JavaScript engine.
  • Authentication bypass via state manipulation: A session that should be invalidated after logout but is not. The code looks correct; the bug is in how session state transitions are handled at runtime.
  • Race conditions: Time-of-check/time-of-use flaws where concurrent requests produce different outcomes than single-threaded analysis predicts.
  • Business logic flaws: An API that returns user A's data when user B authenticates β€” detectable only by making the actual request, not by reading the code.
  • Server misconfiguration: Default headers missing (X-Frame-Options, Content-Security-Policy), directory listing enabled, server version disclosure β€” all visible only at the HTTP response level.

The static analysis gap: Multiple studies have found that SAST tools miss 50–60% of vulnerabilities that DAST finds in the same applications. The classes are different enough that they are genuinely complementary β€” there is minimal overlap in findings.

How DAST works

A DAST tool acts as a proxy between a browser (or HTTP client) and the target application. It:

  1. Crawls the application to discover endpoints, forms, and API parameters
  2. Fuzzes each parameter with attack payloads β€” SQLi strings, XSS vectors, path traversal sequences, command injection strings
  3. Analyses responses for indicators of vulnerability: SQL error messages, reflected payloads, unexpected HTTP status codes, timing differences
  4. Reports confirmed or suspected vulnerabilities with evidence

Active vs passive DAST: Active DAST sends attack payloads β€” it is intrusive and must only run against non-production environments. Passive DAST only observes traffic (like a recording proxy) and finds misconfigurations without sending attacks β€” safe to run against production but lower coverage.

Vulnerability classes DAST finds reliably

  • Reflected and stored XSS β€” payload injected and reflected in response
  • SQL injection β€” error-based, blind, and time-based
  • Broken authentication β€” default credentials, brute-forceable login endpoints
  • IDOR (Insecure Direct Object Reference) β€” parameter manipulation to access other users' data
  • SSRF β€” server-side request forgery via URL parameters
  • Open redirects β€” redirect parameters accepting external URLs
  • Security headers missing β€” CSP, HSTS, X-Frame-Options, etc.
  • Verbose error messages β€” stack traces, SQL errors leaked in responses
  • Directory traversal β€” path parameter manipulation

Integrating DAST into CI/CD pipelines

DAST requires a running application, which means it fits at the staging environment stage of your pipeline β€” after build and deployment, before production release.

Pipeline stages with DASTtext
Code β†’ Build β†’ Unit Tests β†’ SAST/SCA β†’ Deploy to Staging
                                                  ↓
                                          DAST Scan ← (active scan against staging)
                                                  ↓
                                          Gate: block on critical findings
                                                  ↓
                                          Deploy to Production

Never run active DAST against production. Active scanning sends payloads that could corrupt data, create test records, trigger alerts, or cause availability issues. Always scan a staging environment with a dedicated test dataset. Passive DAST (traffic observation) can be run against production safely.

OWASP ZAP in GitHub Actions

.github/workflows/dast.ymlyaml
name: DAST Scan
on:
  push: { branches: [main] }

jobs:
  dast:
    runs-on: ubuntu-latest
    services:
      app:
        image: my-org/my-app:staging
        ports: ["8080:8080"]

    steps:
      - uses: actions/checkout@v4

      - name: ZAP Full Scan
        uses: zaproxy/[email protected]
        with:
          target: http://app:8080
          rules_file_name: .zap/rules.tsv
          cmd_options: -a  # include alpha rules
          allow_issue_writing: false
          fail_action: true  # fail CI on high findings

ZAP configuration for API scanning

.zap/api-scan.yamlyaml
env:
  contexts:
    - name: Target
      urls: [http://staging:8080/api]
      includePaths: ["http://staging:8080/api/.*"]

jobs:
  - type: openapi
    parameters:
      apiFile: openapi.yaml
      context: Target

  - type: activeScan
    parameters:
      context: Target
      policy: API-Scan-Policy

Nuclei for targeted, low-noise scanning

Nuclei is a template-based scanner that runs specific, known-good checks β€” less comprehensive than ZAP's full crawl-and-fuzz approach, but much lower false positive rate. Ideal for checking specific vulnerability classes:

Nuclei β€” targeted security checksshell
# Run only high/critical severity templates
nuclei -u https://staging.internal \
  -severity high,critical \
  -tags owasp \
  -o nuclei-findings.json \
  -json

# Run specific vulnerability categories
nuclei -u https://staging.internal \
  -t cves/ \
  -t exposed-panels/ \
  -t misconfigurations/ \
  -retries 2

DAST limitations to understand

  • Requires a running application: Cannot run in early CI stages without a deployed environment
  • Authentication complexity: Modern SPAs with OAuth/OIDC flows require careful session management for the DAST tool to scan authenticated endpoints
  • Slower than SAST: A full ZAP scan against a complex application can take 30–60 minutes β€” too slow for PR checks, better scheduled against staging
  • Risk of test data pollution: Active scanning creates records in your application database. Use a clean staging environment with disposable data.
  • Cannot find code-level flaws: A vulnerability that requires source code inspection (cryptographic key length, internal logic) is invisible to DAST

DAST completes the security scanner stack

The full DevSecOps security scanner stack β€” from developer workstation to production β€” is:

  • IDE: SAST + secrets (real-time feedback, seconds after writing)
  • Pre-commit: Secrets scanning (blocks commits)
  • CI (PR): SAST + SCA + IaC + secrets (blocks merges)
  • CI (staging): Container scanning + DAST (validates runtime)
  • Production: Passive DAST + runtime monitoring (ongoing detection)

The key insight: DAST is not a replacement for SAST β€” it is the final validation that your application actually behaves securely in the real world, not just that it looks secure in the code. Both are necessary; neither is sufficient alone.

Complete your security programme with DAST

AquilaX DAST integrates into your staging pipeline and provides authenticated scanning, API scanning via OpenAPI specs, and findings that map back to your SAST results for a unified view.

Explore DAST β†’