The ZAP security testing tool is a free, open-source dynamic application security testing (DAST) scanner that finds vulnerabilities in web applications while they are running, and it remains the most widely deployed DAST tool in the world. Originally an OWASP flagship project known as OWASP ZAP (Zed Attack Proxy), the core team joined Checkmarx in 2024 and the project was rebranded ZAP by Checkmarx while staying free and open source.
This guide covers what ZAP does, the difference between its scanning modes, and how to run it as a repeatable check in CI rather than a one-off manual scan.
What ZAP is and how it works
ZAP sits between a browser and the web application as an intercepting proxy. Every request and response flows through it, which lets it observe traffic, modify requests, and inject test payloads. That proxy architecture is the foundation of everything else it does. You can drive it manually through its desktop interface for exploratory testing, or run it headless for automation.
Because it tests a running application, ZAP finds a different class of issue than a static code scanner. It sees what the deployed system actually does with a request, including problems introduced by configuration, server behavior, or the interaction between components that source analysis cannot observe. That is the essence of DAST, and it is why teams run it alongside, not instead of, static analysis.
Passive scanning versus active scanning
The single most important distinction to understand about ZAP is passive versus active scanning, because confusing them causes both missed findings and accidental damage.
Passive scanning analyzes the traffic that already flows through the proxy without sending any additional requests. As you browse the app, or as the spider crawls it, ZAP inspects responses for issues it can detect by observation alone: missing security headers, cookies without the Secure or HttpOnly flags, information disclosure in error messages, and similar. Passive scanning is completely safe to run against any environment because it never sends attack traffic. It only watches.
Active scanning is different. It actively sends crafted attack payloads to the endpoints ZAP has discovered, probing for issues like injection flaws that can only be confirmed by seeing how the application responds to malicious input. Active scanning is intrusive by nature. It can create records, trigger emails, or in a poorly built app cause real changes to data. You run active scanning only against test environments you control and have permission to attack, never against production or third-party systems.
The spider and the AJAX spider
Before ZAP can scan endpoints, it has to find them. It ships two crawlers.
The traditional spider parses HTML responses and follows links, building a map of the application's reachable URLs. It is fast and works well for server-rendered sites.
The AJAX spider exists because the traditional spider cannot see content that only appears after JavaScript runs. Modern single-page applications render most of their routes client-side, so a link-following crawler finds almost nothing. The AJAX spider drives a real headless browser, lets the JavaScript execute, and discovers the endpoints that a modern front end actually calls. For any React, Vue, or Angular application, you need the AJAX spider or your scan coverage will be close to zero. This is the most common reason a ZAP scan comes back suspiciously clean: it never found the real endpoints.
Running ZAP in CI
ZAP is packaged for automation, and the container images make it straightforward to run in a pipeline. There are two common entry points: a baseline scan for a fast, safe check on every build, and a full scan for deeper periodic testing.
The baseline scan runs the spider and passive scanning only. It is fast and safe, so it fits on every pull request:
docker run -t zaproxy/zap-stable zap-baseline.py \
-t https://staging.example.com \
-r zap-report.html
The full scan adds active scanning and is meant for a dedicated test environment, typically on a nightly schedule rather than per-commit:
docker run -t zaproxy/zap-stable zap-full-scan.py \
-t https://staging.example.com \
-r zap-full-report.html
For anything nontrivial you will also want to handle authentication so the scanner can reach pages behind login, and you will want the AJAX spider enabled for a JavaScript-heavy app. ZAP supports SARIF output, which lets findings flow into GitHub code scanning or your own dashboards rather than living in an HTML file nobody opens.
Keeping the findings actionable
The failure mode with any DAST tool is a first scan that returns dozens of findings, many of them low-severity or duplicated across near-identical URLs, and a team that responds by ignoring the report. A few habits prevent that.
Use a configuration file to tune which rules fire and at what threshold, and to mark accepted findings so they stop reappearing without being silently dropped. Baseline the current state so you alert on new findings introduced by a change rather than re-litigating the entire backlog on every run. And separate the fast baseline scan (a build gate) from the deep full scan (a scheduled job), so per-commit feedback stays quick while thorough testing still happens.
DAST is one leg of a complete program. It exercises the running application but does not see your dependency tree or your source. Pairing it with static analysis and software composition analysis gives you the full picture, and a managed DAST service can run ZAP-style scans continuously with authentication and SPA crawling handled for you. For the dependency side, an SCA tool catches the vulnerable components ZAP cannot see. Our Academy walks through combining the two without drowning in duplicate findings.
FAQ
Is the ZAP security testing tool still free after the Checkmarx rebrand?
Yes. The ZAP core team joined Checkmarx in 2024 and the project was renamed ZAP by Checkmarx, but it remains free and open source. Checkmarx funds continued development while the tool stays available to everyone.
What is the difference between passive and active scanning in ZAP?
Passive scanning only analyzes traffic that already flows through the proxy and never sends attack payloads, so it is safe against any environment. Active scanning sends crafted malicious requests to discovered endpoints and is intrusive, so it must only run against test environments you control and have permission to attack.
Why does my ZAP scan find almost nothing on a single-page app?
Because the traditional spider only follows HTML links and cannot see routes rendered by JavaScript. Enable the AJAX spider, which drives a headless browser and lets the JavaScript execute so it can discover the endpoints a React, Vue, or Angular app actually uses.
Can I run ZAP against production?
Run only the passive baseline scan against production, and even that with care, since it still generates traffic and requires authorization. Never run the active full scan against production or any system you do not own, because active scanning sends real attack payloads that can alter data or trigger side effects.