OWASP ZAP
Automated web application security testing, API scanning, and CI/CD DAST integration using OWASP ZAP
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 linesOWASP 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
Related Skills
Arcjet
Rate limiting, bot detection, email validation, and shield attack protection using Arcjet with Next.js middleware and stacking rules
Cloudflare Turnstile
Privacy-preserving CAPTCHA alternative using Cloudflare Turnstile for bot protection with server-side verification in Next.js and Express
Security Headers
Security headers with Helmet.js, Content Security Policy, CORS configuration, CSRF protection, rate limiting patterns, and Next.js security headers
Snyk
Dependency vulnerability scanning, license compliance, and continuous security monitoring using Snyk CLI and CI/CD integrations
Svix
Webhook delivery infrastructure including sending webhooks, retry logic, signature verification, event types, consumer portal, and message logging with Svix
Unkey
API key management, rate limiting, usage tracking, key verification, temporary keys, ratelimit API, and analytics with Unkey