Skip to main content
Technology & EngineeringSecurity Ratelimit206 lines

OWASP ZAP

Automated web application security testing, API scanning, and CI/CD DAST integration using OWASP ZAP

Quick Summary24 lines
You are an expert in using OWASP ZAP (Zed Attack Proxy) for dynamic application security testing (DAST), API security scanning, and automated penetration testing integrated into CI/CD pipelines.

## Key Points

- type: spider
- type: passiveScan-wait
- type: activeScan
- type: report
- Start with baseline (passive) scans in CI on every PR and reserve full active scans for nightly or pre-release pipelines, since active scans take significantly longer.
- Always scan a staging environment, never production — active scans send exploit payloads that can corrupt data or trigger alerts.
- Use the ZAP Automation Framework YAML config instead of CLI flags for reproducible, version-controlled scan configurations.
- Running active scans against production databases — ZAP sends real SQL injection and XSS payloads that can modify or destroy data. Always target isolated staging environments.
- Skipping authenticated scanning — unauthenticated scans only test the login page and public endpoints, missing the vast majority of your application's attack surface.

## Quick Example

```bash
# Use ZAP's automation framework for authenticated scans
# automation.yaml
docker run --rm -v $(pwd):/zap/wrk ghcr.io/zaproxy/zaproxy:stable \
  zap.sh -cmd -autorun /zap/wrk/automation.yaml
```
skilldb get security-ratelimit-skills/OWASP ZAPFull skill: 206 lines
Paste into your CLAUDE.md or agent config

OWASP ZAP — Security & Rate Limiting

You are an expert in using OWASP ZAP (Zed Attack Proxy) for dynamic application security testing (DAST), API security scanning, and automated penetration testing integrated into CI/CD pipelines.

Core Philosophy

Overview

OWASP ZAP is an open-source DAST tool that finds vulnerabilities in running web applications by actively probing them — SQL injection, XSS, broken authentication, security misconfigurations, and more. Unlike static analysis tools, ZAP tests your application as a black box by sending real HTTP requests. It can run as an interactive GUI for manual testing or as a headless daemon for automated CI/CD scans. ZAP provides baseline scans (passive, fast), full scans (active, thorough), and API scans (OpenAPI/GraphQL).

Setup & Configuration

Docker-Based Setup (Recommended for CI)

# Pull the stable ZAP Docker image
docker pull ghcr.io/zaproxy/zaproxy:stable

# Run a quick baseline scan against a target
docker run --rm ghcr.io/zaproxy/zaproxy:stable \
  zap-baseline.py -t https://your-app.example.com \
  -r report.html

# Run a full active scan (longer, more thorough)
docker run --rm ghcr.io/zaproxy/zaproxy:stable \
  zap-full-scan.py -t https://your-app.example.com \
  -r full-report.html

API Scan with OpenAPI Spec

# Scan an API using its OpenAPI definition
docker run --rm -v $(pwd):/zap/wrk ghcr.io/zaproxy/zaproxy:stable \
  zap-api-scan.py \
  -t https://your-app.example.com/openapi.json \
  -f openapi \
  -r api-report.html

CI/CD Integration (GitHub Actions)

# .github/workflows/zap-scan.yml
name: OWASP ZAP Scan
on:
  push:
    branches: [main]

jobs:
  zap-baseline:
    runs-on: ubuntu-latest
    steps:
      - name: ZAP Baseline Scan
        uses: zaproxy/action-baseline@v0.14.0
        with:
          target: "https://your-staging-app.example.com"
          rules_file_name: "zap-rules.tsv"
          fail_action: true

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

Core Patterns

Rules Configuration File

# zap-rules.tsv — Control which alerts fail the build
# Format: rule_id	action (WARN, FAIL, IGNORE)
10021	WARN
10038	IGNORE
40012	FAIL
40014	FAIL
90033	WARN

Authenticated Scanning

# Use ZAP's automation framework for authenticated scans
# automation.yaml
docker run --rm -v $(pwd):/zap/wrk ghcr.io/zaproxy/zaproxy:stable \
  zap.sh -cmd -autorun /zap/wrk/automation.yaml
# automation.yaml — ZAP Automation Framework config
---
env:
  contexts:
    - name: "my-app"
      urls:
        - "https://your-app.example.com"
      authentication:
        method: "browser"
        parameters:
          loginPageUrl: "https://your-app.example.com/login"
          loginPageWait: 5
        verification:
          method: "response"
          loggedInRegex: "Sign Out"
      users:
        - name: "test-user"
          credentials:
            username: "testuser@example.com"
            password: "${ZAP_AUTH_PASSWORD}"
  parameters:
    failOnError: true
    progressToStdout: true

jobs:
  - type: spider
    parameters:
      context: "my-app"
      user: "test-user"
      maxDuration: 5
  - type: passiveScan-wait
    parameters:
      maxDuration: 5
  - type: activeScan
    parameters:
      context: "my-app"
      user: "test-user"
      maxRuleDurationInMins: 5
  - type: report
    parameters:
      template: "modern"
      reportDir: "/zap/wrk"
      reportFile: "zap-report"
    risks:
      - high
      - medium

Parsing ZAP JSON Reports Programmatically

import { readFileSync } from "fs";

interface ZapAlert {
  name: string;
  riskcode: string;
  confidence: string;
  count: string;
  instances: Array<{ uri: string; method: string; param: string }>;
}

interface ZapReport {
  site: Array<{ alerts: ZapAlert[] }>;
}

function parseZapReport(reportPath: string) {
  const report: ZapReport = JSON.parse(
    readFileSync(reportPath, "utf-8")
  );

  const highRisk = report.site.flatMap((site) =>
    site.alerts.filter((alert) => parseInt(alert.riskcode) >= 3)
  );

  if (highRisk.length > 0) {
    console.error(
      `Found ${highRisk.length} high-risk vulnerabilities:`
    );
    highRisk.forEach((alert) => {
      console.error(`  - ${alert.name} (${alert.count} instances)`);
    });
    process.exit(1);
  }
}

Best Practices

  • Start with baseline (passive) scans in CI on every PR and reserve full active scans for nightly or pre-release pipelines, since active scans take significantly longer.
  • Always scan a staging environment, never production — active scans send exploit payloads that can corrupt data or trigger alerts.
  • Use the ZAP Automation Framework YAML config instead of CLI flags for reproducible, version-controlled scan configurations.

Common Pitfalls

  • Running active scans against production databases — ZAP sends real SQL injection and XSS payloads that can modify or destroy data. Always target isolated staging environments.
  • Skipping authenticated scanning — unauthenticated scans only test the login page and public endpoints, missing the vast majority of your application's attack surface.

Anti-Patterns

Over-engineering for hypothetical requirements. Building for scenarios that may never materialize adds complexity without value. Solve the problem in front of you first.

Ignoring the existing ecosystem. Reinventing functionality that mature libraries already provide wastes time and introduces risk.

Premature abstraction. Creating elaborate frameworks before having enough concrete cases to know what the abstraction should look like produces the wrong abstraction.

Neglecting error handling at system boundaries. Internal code can trust its inputs, but boundaries with external systems require defensive validation.

Skipping documentation. What is obvious to you today will not be obvious to your colleague next month or to you next year.

Install this skill directly: skilldb add security-ratelimit-skills

Get CLI access →