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 Type Duration Coverage Use Case
Baseline 1-5 min Low PR checks, quick validation
Full 30-120 min High Nightly scans, pre-release
API 5-30 min API only REST/GraphQL testing
Ajax Spider 15-60 min SPAs React, 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

Optimization How
Limit spider depth --spider.maxDepth=5
Exclude static assets `--exclude='.*.(css
Use baseline for PRs Faster, common vulns only
Run full scans nightly Off peak hours
Cache ZAP Docker image Use docker pull step

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

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.