zap-baseline
Configures and runs OWASP ZAP baseline scanning: `zap-baseline.py` Docker-packaged spider + passive scan suitable for CI gating; supports `-t target_url` + `-r html_report` + `-c config_file` rule customization (INFO/IGNORE/FAIL warnings) and Ajax spider via `-j` for JS-heavy SPAs. Passive-only; for active injection probes use `zap-full-scan.py` via zap-authenticated-scans. Accepts `-n context_file` for pre-configured auth contexts (see zap-authenticated-scans for setting up auth from scratch). Use when the user runs OWASP ZAP for pre-prod web app DAST.
Install with skills.sh (any agent)
npx skills add testland/qa --skill zap-baselinezap-baseline
Overview
Per zaproxy.org/docs/docker/baseline-scan/ (opens in new window):
"The ZAP Baseline scan is a script that is available in the ZAP Docker images. It runs the ZAP spider against the specified target for (by default) 1 minute and then waits for the passive scanning to complete before reporting the results."
The baseline scan is passive only - non-intrusive, safe for production. The companion zap-full-scan.py adds active scanning (injection probes, XSS payloads) and is NOT safe for production; reserve for staging.
When to use
Step 1 - Install
ZAP baseline runs from the official Docker image - no host install needed. Per zap-base (opens in new window):
docker pull ghcr.io/zaproxy/zaproxy:stableImage variants:
| Tag | Use |
|---|---|
:stable | Production-grade; pin in CI |
:weekly | Latest features; for evaluation |
:bare | Headless minimal; smallest |
Step 2 - First baseline scan
Per zap-base (opens in new window) (verbatim):
docker run -v $(pwd):/zap/wrk/:rw -t ghcr.io/zaproxy/zaproxy:stable zap-baseline.py \
-t https://www.example.com -r testreport.htmlThe -v $(pwd):/zap/wrk/:rw mount makes the report writable to the host directory. The report file lands at ./testreport.html after the scan.
Step 3 - Common flags
Per zap-base (opens in new window):
| Flag | Use |
|---|---|
-t URL | Target URL (required) |
-r FILE | HTML report output |
-w FILE | Markdown report |
-x FILE | XML report |
-J FILE | JSON report (for finding triage) |
-c FILE | Config file: rule INFO/IGNORE/FAIL behavior |
-P PORT | Specify ZAP listen port |
-j | Use Ajax spider in addition to traditional spider (JS-heavy apps) |
-m MINS | Spider duration in minutes (default 1) |
-d | Show debug messages |
-I | Don't return failure on warning (gate softly) |
-n CONTEXT_FILE | Authenticated scan context file |
Step 4 - Authenticated scans
For apps requiring login, export a ZAP context file from the GUI (Sites → right-click → Export Context). The context file encodes:
Then:
docker run -v $(pwd):/zap/wrk/:rw \
-e ZAP_AUTH_USERNAME=$USER \
-e ZAP_AUTH_PASSWORD=$PASS \
-t ghcr.io/zaproxy/zaproxy:stable \
zap-baseline.py -t https://app.example.com -n /zap/wrk/context.xml -J report.jsonStep 5 - Active scan companion (zap-full-scan.py)
For staging-only deeper analysis:
docker run -v $(pwd):/zap/wrk/:rw -t ghcr.io/zaproxy/zaproxy:stable \
zap-full-scan.py -t https://staging.example.com -J report.jsonzap-full-scan.py triggers active payloads (SQLi probes, XSS, SSRF). NEVER point at production - risk of data corruption + generates audit-log noise.
Step 6 - False-positive triage (MANDATORY)
Per zap-base (opens in new window), rule customization via -c config_file where each line is <rule_id>\t<INFO|WARN|IGNORE|FAIL>\t<URL_pattern>:
Example zap-config.tsv:
10049 IGNORE * # Cookie No HttpOnly: legacy session cookie; tracked in JIRA-1234
40012 WARN https://app.example.com/admin/* # XSS: legacy admin pages; not exposed to users
10063 FAIL * # Permissions Policy: must be set on all responsesThree suppression layers:
| Mechanism | Example | When to use |
|---|---|---|
| Per-rule config TSV | <rule_id>\tIGNORE\t* | Rule disabled globally |
| Per-URL pattern | <rule_id>\tWARN\thttps://app/admin/* | Rule downgraded for known-old code path |
| Context exclusion | <exclude_from_context> in context XML | Whole URL trees out of scope |
-I flag | zap-baseline.py -I ... | Soft gate: warns but exits 0 |
Justification template (mandatory in config):
# Rule 10049 (Cookie No HttpOnly)
# Suppressed: 2026-05-15 by alice@example.com
# Reason: legacy session cookie; tracked in JIRA-1234; expires 2026-09-15
# Re-review-date: 2026-09-15
10049 IGNORE *Cadence: every quarter, audit the config TSV - every IGNORE entry should have an Re-review-date. Past-due entries are removed + re-evaluated.
Step 7 - Output formats for cross-tool triage
docker run -v $(pwd):/zap/wrk/:rw -t ghcr.io/zaproxy/zaproxy:stable \
zap-baseline.py -t https://app.example.com -J zap-report.jsonThe JSON report feeds cross-tool aggregation. For SARIF output (GitHub Code Scanning), use a converter (zap-sarif container action).
Step 8 - CI integration
GitHub Actions:
jobs:
zap-baseline:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: zaproxy/action-baseline@v0.13.0
with:
target: 'https://staging.example.com'
rules_file_name: '.zap/rules.tsv'
cmd_options: '-J zap-report.json'
- uses: actions/upload-artifact@v4
if: always()
with: { name: zap-report, path: zap-report.json }The official zaproxy/action-baseline action wraps the Docker invocation. Auto-creates a GitHub Issue on failure.
Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
Run zap-full-scan.py against production | Active payloads pollute / damage data | Staging-only (Step 5) |
Skip -J JSON output | Can't feed finding triage; report is HTML-only | Always pass -J (Step 7) |
| Ignore Ajax spider for SPAs | Missing routes; coverage gap | Add -j flag (Step 3) |
| Hardcode credentials in context file | Secrets leak in repo | Reference env vars (Step 4) |
Suppress without # Re-review-date | Permanent debt | Required template (Step 6) |
Limitations
References
Related skills
burp-headless
Configures and runs headless Burp Suite Professional / Enterprise vulnerability scans (a "Burp scan"): Pro drives scans via its local REST API, Enterprise runs CI-driven scans at scale via its server API; supports BApp Store extensions (BCheck, custom scanners) and authenticated targets via session-handling rules; exports issues as HTML / XML / CSV / JSON or SARIF. Use when the team has a Burp Suite license and wants to run a vulnerability scan with Burp - paid-tier dynamic application security testing (DAST) layered on top of OWASP ZAP.
dast-scan-cadence-author
Designs an end-to-end DAST cadence for teams adopting dynamic scanning: ZAP passive baseline (PR-blocking) then ZAP full active scan (nightly on staging) then optional Burp Pro deep scan (per-release). Handles the baseline-finding ratchet for legacy apps so pre-existing findings do not immediately block PRs, plus per-tool per-run deduplication and CI workflow YAML. Use when the team is setting up DAST from scratch or restructuring scan cadence, not when tools are already running and you need to merge their output (cross-tool aggregation of existing independent runs is a separate concern).
nightvision-dast
Configures and runs NightVision white-box-assisted DAST: analyzes source code before attacking, traces every finding to its origin line, and drives coverage from OpenAPI / Postman / GraphQL specs rather than crawling. Supports Header, Cookie, TOTP, and recorded Interactive Login auth; exports findings as SARIF for GitHub Code Scanning, plus JSON, CSV, or PDF. Per-finding suppression via Alert Rules; CLI integration via the `nightvision` command. Use when source-traceable findings and spec-driven request coverage matter, not just authenticated black-box scanning (see zap-authenticated-scans for that).
nuclei-dast
Installs and runs ProjectDiscovery Nuclei template-based HTTP scanning: selects templates via `-t {path}` and `-tags`/`-severity` filters, controls request rate with `-rl`, emits JSONL output via `-j` for cross-tool finding aggregation, authors custom YAML matchers for app-specific checks, and gates CI on severity thresholds. Use when the team runs Nuclei alongside ZAP for template-driven DAST coverage, needs fuzzing-style probes beyond ZAP passive scan, or wants to operationalize community CVE templates in a pipeline.
zap-authenticated-scans
Configures authenticated DAST sessions in ZAP - ZAP Context + Authentication Method (form, JSON, script, browser-based, HTTP/NTLM), Session Management strategy (cookie, header, script), Verification Strategy (regex indicators, poll-URL), CSRF token handling, OAuth/bearer header injection, logged-in/logged-out indicator calibration, and context XML export for use with `-n` in baseline and full scans. Use when the team needs DAST coverage of authenticated routes - the most common DAST gap and the hardest DAST setup to get right.