OWASP ZAP
OWASP ZAP: free DAST tool, used defensively. Baseline scans, authenticated scans, and how to integrate into CI without breaking developer flow.
Ethical hacking — OWASP ZAP (defensively)
EXAMPLE
# RoE FIRST. Authorised testing only. Use ZAP against systems you own or have written permission to test.
# Run against staging that mirrors prod. Never against arbitrary internet targets.
# ===== What ZAP is =====
# Open-source web application security scanner from OWASP.
# - Passive scanning: observes traffic, flags issues without sending anything dangerous
# - Active scanning: sends crafted requests; only on authorised targets
# - Spider + AJAX spider: discovers URLs
# - Scripted automation framework + REST API + Docker images
# ===== Modes =====
# Safe mode: passive only
# Protected: interactive sessions; safer defaults
# Standard: all actions enabled
# ATTACK: maximum aggression — use ONLY on systems you fully own
# ===== Install =====
# Docker (recommended for CI):
docker pull zaproxy/zap-stable
# Native: download from owasp.org/www-project-zap
# ===== Baseline scan (passive, safe) =====
docker run --rm -t zaproxy/zap-stable zap-baseline.py \
-t https://staging.example.com \
-r baseline-report.html \
-m 5
# Crawls + passively analyses. ~5 minutes typical. Safe to run weekly.
# ===== Authenticated scan =====
# Use the Automation Framework with a login script.
# .zap/automation.yaml
env:
contexts:
- name: app
urls: [https://staging.example.com]
authentication:
method: script
parameters:
scriptName: login.js
scriptEngine: ECMAScript
loggedInIndicator: 'Sign out'
users:
- name: scanbot
credentials:
username: ${SCAN_USER}
password: ${SCAN_PASS}
jobs:
- type: spider
parameters: { context: app, user: scanbot, maxDuration: 5 }
- type: passiveScan-wait
- type: activeScan
parameters: { context: app, user: scanbot, policy: 'Default Policy' }
- type: report
parameters: { template: 'sarif-json', reportDir: reports/ }
# Run:
docker run --rm -v $PWD/.zap:/zap/wrk zaproxy/zap-stable zap.sh -cmd -autorun /zap/wrk/automation.yaml
# ===== CI integration (GitHub Actions) =====
name: dast
on:
schedule:
- cron: '0 4 * * 1' # weekly
workflow_dispatch:
jobs:
zap:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: ZAP baseline
uses: zaproxy/action-baseline@v0.13.0
with:
target: ${{ secrets.STAGING_URL }}
rules_file_name: '.zap/rules.tsv' # false-positive allowlist
# False-positive allowlist (.zap/rules.tsv):
# 10038\tIGNORE\t # CSP missing on /healthz
# 10063\tIGNORE\t # Permissions-Policy not set on docs
# ===== Result triage =====
# - Critical / High: fix before next deploy
# - Medium: ticket + 30-day SLA
# - Low / Info: backlog
# - False positives: allowlist with REASON + reviewer
# ===== Common findings + fixes =====
# Missing Content-Security-Policy add CSP header
# Cookie without Secure / HttpOnly set both flags
# X-Frame-Options absent add or CSP frame-ancestors
# CORS misconfig tighten origins
# Server fingerprint exposed remove Server header
# ===== Don'ts =====
# - Run active scans against production
# - Scan third-party services (out of scope)
# - Ignore findings without writing them up
# - Allowlist without expiry / reviewer
# ===== Patterns to internalise =====
# - Baseline weekly in CI; authenticated scan monthly
# - Per-project .zap/rules.tsv allowlist
# - SARIF output -> GitHub code-scanning alerts
# - Pair findings with code reviews to ship fixes fast
# ===== Pitfalls =====
# - Pointing the scanner at prod
# - Allowlists with no expiry -> findings rot
# - Scanning with a low-privilege user (misses authenticated surface)
# - Treating ZAP as the only DAST (add Burp, nuclei for coverage)
Why it matters
OWASP ZAP is the free DAST workhorse. Baseline weekly on staging, authenticated monthly, allowlists with reasons + expiry. Integrate with CI via Docker + GitHub Actions; treat findings like failing tests. Authorised use only; never the open internet.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
# OWASP ZAP — open-source alternative to Burp. # Baseline scan against staging (with permission): zap-baseline.py -t https://target.example -r baseline.html # Use as the DAST step in CI for apps you OWN.Try it Yourself »
Discussion
Loading…