Dynamic Application Security Testing with OWASP ZAP: Scans, Output, and Failures
The Dynamic Analysis Using ZAP exercise teaches how to run OWASP ZAP baseline scans against web applications. This exercise appears across 5 courses. This article covers scan configuration, output formats, and common failures.
Table of Contents
- ZAP Baseline Scan Command
- Target URL Must Be Accessible
- Scan Takes 5+ Minutes
- JSON Output with Volume Mount
- Authenticated Scans
- Scan Result Categories
- Machine Timeout and 404 Errors
- Common Questions
ZAP Baseline Scan Command
Running a Baseline Scan
The exercise uses the hysnsec/zap:2.16.1 Docker image:
docker run --rm hysnsec/zap:2.16.1 zap-baseline.py -t https://prod-<machine-id>.lab.practical-devsecops.training
Key concept: The Docker image is auto-pulled if not present locally. No need for docker pull first.
Baseline Scan Options
| Flag | Purpose |
|---|---|
-t target |
Target URL with protocol (required) |
-m mins |
Minutes to spider (default: 1) |
-l level |
Minimum level: PASS, IGNORE, INFO, WARN, FAIL |
-J file.json |
JSON report output |
-r file.html |
HTML report output |
-w file.md |
Markdown report output |
-x file.xml |
XML report output |
-I |
Don't fail on warnings |
-a |
Include alpha passive scan rules |
-j |
Use Ajax spider |
Target URL Must Be Accessible
Connection Refused or Timeout
If the target application isn't running or isn't reachable from the DevSecOps Box:
ERROR: Target URL is not accessible
Fix: Verify the target is up:
curl -s -o /dev/null -w "%{http_code}" https://prod-<machine-id>.lab.practical-devsecops.training
A 200 response means the target is accessible. 000 means connection refused.
Wrong URL Pattern
The target URL must use the correct pattern:
https://prod-<machine-id>.lab.practical-devsecops.training
Common mistake: Using http:// instead of https://, or omitting the protocol entirely. ZAP requires the full URL with protocol.
Scan Takes 5+ Minutes <a name="scan-timing>
Be Patient During the Scan
The ZAP baseline scan involves spidering the target application, which can take 5+ minutes depending on the number of pages:
[INFO] Passing the 'view' to the scanner...
[INFO] Passive scan queue size: 0 Passive scan thread limit: 0
[INFO] Acquisition [SPIDER] Complete.
Common mistake: Assuming the scan failed because there's no output for several minutes. ZAP is silent during active scanning.
Fix: Wait for the full scan to complete. The summary line at the end shows all findings:
FAIL-NEW: 0 FAIL-INPROG: 0 WARN-NEW: 17 WARN-INPROG: 0 INFO: 0 IGNORE: 0 PASS: 48
JSON Output with Volume Mount
Saving Scan Results to a File
To save results as JSON, use a volume mount:
docker run --user $(id -u):$(id -g) -w /zap -v $(pwd):/zap/wrk:rw --rm hysnsec/zap:2.16.1 zap-baseline.py -t https://prod-<machine-id>.lab.practical-devsecops.training -J zap-output.json
Flags explained:
| Flag | Purpose |
|---|---|
--user $(id -u):$(id -g) |
Run as current user for file permissions |
-w /zap |
Working directory inside container |
-v $(pwd):/zap/wrk:rw |
Mount current directory for output |
-J zap-output.json |
Write JSON report |
Verify the Output
cat zap-output.json
Common mistake: Forgetting the volume mount. Without -v, the JSON file is created inside the container and is lost when the container exits.
Authenticated Scans
Scanning Protected Areas
For applications that require login, use the context file and user flags:
docker run --rm hysnsec/zap:2.16.1 zap-baseline.py \
-t https://prod-<machine-id>.lab.practical-devsecops.training \
-n context-file.json \
-U username
Key concept: Without authentication, ZAP can only scan publicly accessible pages. Protected endpoints won't be tested.
Scan Result Categories
Understanding the Summary
ZAP classifies findings into these categories:
| Category | Meaning |
|---|---|
FAIL-NEW |
New high-severity vulnerabilities that should be fixed immediately |
FAIL-INPROG |
Known failures being worked on |
WARN-NEW |
New warnings — should be reviewed |
WARN-INPROG |
Known warnings being monitored |
INFO |
Informational findings |
IGNORE |
Suppressed findings |
PASS |
Checks that passed |
Common Warnings
Typical baseline scan results include:
- Strict-Transport-Security Header Not Set [10035] — HSTS not configured
- Server Leaks Version Information [10036] — Server header exposes version
- Permissions Policy Header Not Set [10063] — Feature policy not configured
- Source Code Disclosure - SQL [10099] — SQL error messages visible
These are warnings, not failures. They indicate areas for improvement.
Machine Timeout and 404 Errors
Two Machines: DevSecOps Box and Production
This exercise uses 2 machines: DevSecOps Box (where you run ZAP) and Production (the target application).
- 2-hour timeout applies to both machines independently.
- If the Production machine times out, ZAP scans will fail with connection errors.
- 404 errors mean the machine was recycled.
Fix: Refresh the exercise page and click Start the Exercise again.
Common Questions
| Question | Answer |
|---|---|
| The ZAP scan seems stuck with no output. | Normal. Scans take 5+ minutes. Wait for the summary line. |
| How do I save the scan results to a file? | Use -J zap-output.json with a volume mount: -v $(pwd):/zap/wrk:rw. |
| My target URL returns connection refused. | The production application may not be fully started yet. Wait 30 seconds and retry. |
| Can I adjust how long ZAP spiders the target? | Yes, use -m mins (default is 1 minute). |
What does WARN-NEW: 17 mean? |
17 new warnings were found. These should be reviewed but aren't critical failures. |
Do I need to docker pull the ZAP image first? |
No. docker run auto-pulls if the image isn't present. |
Wrap-Up
OWASP ZAP baseline scans are a quick way to find web application security issues. Key takeaways:
zap-baseline.py -t <URL>is the core command. The URL must include the protocol (https://).- Scans take 5+ minutes — be patient and wait for the summary.
- JSON output requires a volume mount (
-v $(pwd):/zap/wrk:rw) and--user $(id -u):$(id -g). - WARN-NEW findings are common and expected for unhardened applications.
- Two machines are involved (DevSecOps Box + Production), both with 2-hour timeouts.
The DevSecOps Box is stateless — all scan outputs are lost on page refresh.