OWASP ZAP — Web Application Security Scanner
OWASP ZAP (Zed Attack Proxy) is the world's most widely used open-source web application security scanner. It finds vulnerabilities in web apps through active scanning, passive analysis, and manual testing.
✅ Pros
- + Best-in-class DAST: finds real vulnerabilities in running applications (XSS, SQLi, etc.)
- + Free and open-source — enterprise-grade web security testing without licensing costs
- + Built-in automation mode for CI/CD integration with Docker and GitHub Actions
- + Huge community, extensive documentation, and active development
- + REST API for programmatic control — automate complex scan workflows
⚠️ Cons
- − Active scanning can disrupt staging environments if not carefully targeted
- − GUI is dated and complex for beginners
- − False positive rate requires manual verification for CI gates
- − Modern SPAs and JavaScript-heavy apps require additional configuration
What is OWASP ZAP?
OWASP ZAP (Zed Attack Proxy) is the world’s most widely used free security tool for finding vulnerabilities in web applications. It’s both an intercepting proxy (like Burp Suite) for manual testing and an automated scanner that can be integrated into CI/CD pipelines.
ZAP finds vulnerabilities from the OWASP Top 10 and beyond:
- SQL injection
- Cross-site scripting (XSS)
- Broken authentication
- Sensitive data exposure
- Security misconfigurations
- Insecure direct object references
Quick Start
# Run ZAP in Docker (automated scan)
docker run -t owasp/zap2docker-stable zap-baseline.py \
-t https://your-staging-app.example.com \
-r zap-report.html
# Full scan (more thorough, longer)
docker run -t owasp/zap2docker-stable zap-full-scan.py \
-t https://your-staging-app.example.com \
-r zap-report.html
# API scan
docker run -t owasp/zap2docker-stable zap-api-scan.py \
-t https://api.example.com/openapi.json \
-f openapi \
-r api-scan-report.html
Scan Types
Baseline Scan
Passive scan only — no active attacks. Finds obvious misconfigurations and security headers. Safe for production (no dangerous requests):
zap-baseline.py -t https://app.example.com \
-J baseline-report.json \
-I # Ignore warnings (only fail on alerts)
Full Scan
Active scanning — attempts actual attack payloads. Use only on staging/test environments:
zap-full-scan.py -t https://staging.example.com \
-J full-scan-report.json \
-m 10 # Max crawl time in minutes
API Scan
Targeted at REST APIs using OpenAPI/Swagger or GraphQL schemas:
zap-api-scan.py \
-t https://api.example.com/openapi.yaml \
-f openapi \
-J api-report.json \
-d # Enable debug output
CI/CD Integration
GitHub Actions
name: ZAP Security Scan
on:
push:
branches: [main]
jobs:
zap-scan:
runs-on: ubuntu-latest
steps:
- name: Start test application
run: docker-compose up -d
- name: ZAP Baseline Scan
uses: zaproxy/[email protected]
with:
target: 'http://localhost:3000'
rules_file_name: '.zap/rules.tsv'
fail_action: false # Set true to fail on findings
- name: Upload ZAP Report
uses: actions/upload-artifact@v4
if: always()
with:
name: zap-report
path: report_html.html
GitLab CI
zap-scan:
image: owasp/zap2docker-stable
stage: security
script:
- zap-baseline.py -t $STAGING_URL -J zap-report.json
artifacts:
reports:
security: zap-report.json
paths:
- zap-report.json
allow_failure: true
Automation Framework
ZAP 2.x introduced the Automation Framework — YAML-based scan configuration:
# zap-automation.yaml
env:
contexts:
- name: "My App"
urls:
- "https://staging.example.com"
includePaths:
- "https://staging.example.com/api/.*"
excludePaths:
- "https://staging.example.com/logout"
jobs:
- type: passiveScan-config
parameters:
maxAlertsPerRule: 10
- type: spider
parameters:
maxDuration: 5 # minutes
- type: activeScan
parameters:
maxRuleDurationInMins: 5
- type: report
parameters:
template: "modern"
reportDir: "/reports"
reportFile: "zap-report"
# Run with automation framework
docker run -v $(pwd):/zap/wrk:rw \
owasp/zap2docker-stable \
zap.sh -cmd -autorun /zap/wrk/zap-automation.yaml
Managing False Positives
Control which rules run and their alert levels:
# .zap/rules.tsv
# Rule ID Action Parameter
10016 IGNORE # Web Browser XSS Protection Not Enabled (legacy header)
10020 IGNORE # X-Frame-Options Header
10021 WARN # X-Content-Type-Options Header Missing
Authenticated Scanning
ZAP supports multiple authentication methods for scanning behind login:
# Form-based authentication
authentication:
method: "form"
parameters:
loginUrl: "https://app.example.com/login"
loginRequestData: "username={%username%}&password={%password%}"
users:
- name: testuser
credentials:
username: [email protected]
password: testpassword
ZAP is the go-to tool for DAST (Dynamic Application Security Testing) when you need to understand what vulnerabilities actually exist in your running application — not just in your source code.