Dynamic Testing & Runtime Security

OWASP ZAP Automation in Pipelines

3 min read

OWASP ZAP (Zed Attack Proxy) is the world's most popular free DAST tool. Here's how to integrate it into your CI/CD pipeline.

ZAP Scan Types

Scan TypeDurationCoverageUse Case
Baseline1-5 minLowPR checks, quick validation
Full30-120 minHighNightly scans, pre-release
API5-30 minAPI onlyREST/GraphQL testing
Ajax Spider15-60 minSPAsReact, Vue, Angular apps

GitHub Actions Integration

Baseline Scan (Fast)

# .github/workflows/dast-baseline.yml
name: DAST Baseline Scan

on:
  pull_request:
    branches: [main]

jobs:
  zap-baseline:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to staging
        run: |
          # Your deployment script
          echo "Deploying to staging..."

      - name: ZAP Baseline Scan
        uses: zaproxy/action-baseline@v0.10.0
        with:
          target: 'https://staging.example.com'
          rules_file_name: '.zap/rules.tsv'
          cmd_options: '-a'  # Include alpha rules

      - name: Upload ZAP Report
        uses: actions/upload-artifact@v4
        with:
          name: zap-report
          path: report_html.html

Full Scan (Comprehensive)

# .github/workflows/dast-full.yml
name: DAST Full Scan

on:
  schedule:
    - cron: '0 2 * * *'  # 2 AM daily

jobs:
  zap-full:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: ZAP Full Scan
        uses: zaproxy/action-full-scan@v0.9.0
        with:
          target: 'https://staging.example.com'
          rules_file_name: '.zap/rules.tsv'
          cmd_options: >
            -j  # Use Ajax spider
            -m 5  # Spider timeout 5 min

      - name: Upload Results to GitHub Security
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: 'zap-results.sarif'

Configuring ZAP Rules

Create custom rules to tune scan behavior:

# .zap/rules.tsv
# ID	Action	Name
10021	IGNORE	X-Content-Type-Options Header Missing
10038	WARN	Content Security Policy (CSP) Header Not Set
40012	FAIL	Cross Site Scripting (Reflected)
40014	FAIL	Cross Site Scripting (Persistent)
90022	FAIL	Application Error Disclosure

Actions:

  • IGNORE: Don't report (false positive)
  • WARN: Report but don't fail pipeline
  • FAIL: Report and fail pipeline

Authenticated Scanning

Most apps require login. Use ZAP's authentication options:

Option 1: Context File

# .zap/context.xml
<context>
  <name>MyApp</name>
  <authentication>
    <type>formBasedAuthentication</type>
    <loginUrl>https://app.example.com/login</loginUrl>
    <loginRequestBody>username={%username%}&amp;password={%password%}</loginRequestBody>
  </authentication>
  <users>
    <user>
      <name>test-user</name>
      <credentials>
        <username>testuser</username>
        <password>${ZAP_AUTH_PASSWORD}</password>
      </credentials>
    </user>
  </users>
</context>
# GitHub Actions with auth
- name: ZAP Full Scan
  uses: zaproxy/action-full-scan@v0.9.0
  with:
    target: 'https://staging.example.com'
    docker_name: 'ghcr.io/zaproxy/zaproxy:stable'
  env:
    ZAP_AUTH_PASSWORD: ${{ secrets.ZAP_AUTH_PASSWORD }}

Option 2: Authorization Header

# For API/JWT authentication
- name: ZAP API Scan
  uses: zaproxy/action-api-scan@v0.6.0
  with:
    target: 'https://api.example.com/openapi.json'
    cmd_options: >
      -z "replacer.full_list(0).description=auth"
      -z "replacer.full_list(0).enabled=true"
      -z "replacer.full_list(0).matchtype=REQ_HEADER"
      -z "replacer.full_list(0).matchstr=Authorization"
      -z "replacer.full_list(0).replacement=Bearer ${{ secrets.API_TOKEN }}"

Handling Results

Fail on Critical Findings

- name: Check ZAP Results
  run: |
    if grep -q "FAIL-NEW" zap-results.json; then
      echo "New vulnerabilities found!"
      exit 1
    fi

Create GitHub Issues

- name: Create Issue on Failure
  if: failure()
  uses: actions/github-script@v7
  with:
    script: |
      github.rest.issues.create({
        owner: context.repo.owner,
        repo: context.repo.repo,
        title: 'DAST Scan Found Vulnerabilities',
        body: 'Check the ZAP report in the workflow artifacts.',
        labels: ['security', 'dast']
      })

Performance Tips

OptimizationHow
Limit spider depth--spider.maxDepth=5
Exclude static assets`--exclude='.*.(css
Use baseline for PRsFaster, common vulns only
Run full scans nightlyOff peak hours
Cache ZAP Docker imageUse docker pull step

Next, we'll explore API security testing with Nuclei. :::

Quick check: how does this lesson land for you?

Quiz

Module 4: Dynamic Testing & Runtime Security

Take Quiz
FREE WEEKLY NEWSLETTER

Stay on the Nerd Track

One email per week — courses, deep dives, tools, and AI experiments.

No spam. Unsubscribe anytime.