OWASP ZAP 2.16: New Features and Scan Comparison Notes

Notes on OWASP ZAP 2.16: new features, performance observations, and differences from paid scanners.

10 min read
ibrahimsql
1,871 words

OWASP ZAP 2.16: New Features and Scan Comparison Notes#

OWASP ZAP (Zed Attack Proxy) has long been the "free alternative" to Burp Suite. With version 2.16, it's proving to be much more than that.

Key Updates#

1. Enhanced HUD#

The Heads Up Display (HUD) brings the ZAP interface directly into your browser. It's smoother and more responsive in 2.16, making manual testing significantly faster.

2. Automation Framework#

ZAP's automation framework allows you to define scan pipelines in YAML. This is a useful tool for CI/CD integration.

env: contexts: - name: "Target" urls: - "https://target.com" jobs: - type: spider - type: activeScan - type: report

3. Improved API Support#

Better handling of GraphQL and SOAP APIs means ZAP can now effectively scan modern backends.

Performance#

Scanning speed has improved noticeably. The crawl engine handles Single Page Applications (SPAs) better, reducing the number of missed endpoints.

Verdict#

If you haven't looked at ZAP in a while, 2.16 is the time to reconsider. For automated DAST in your pipeline, it is arguably the best tool available.

Feature Notes From 2.16#

  • HUD updates: panels render inline in the page; theme stays consistent with ZAP chrome. Less alt-tabbing between proxy and site.
  • Automation framework: plans are YAML-driven; you declare env, environment contexts, and rules, then zap.sh -cmd -autorun plan.yaml runs them.
  • WebSocket support: message view and breakpoints for WS frames; useful for chat and push APIs.
  • OpenAPI import: point ZAP at the spec and it seeds the site tree before scanning.

Comparison Baseline#

ScannerStrengthGap
ZAP 2.16Free, scriptable, plugin ecosystemNo IAST coverage built in
Burp ProPolish, Repeater history, IntruderPaid, resource heavy
NucleiTemplate speed, community coverageNot interactive
CaidoFast lightweight proxySmaller plugin set

ZAP's niche is CI: run the baseline scan on every deploy and gate on new alerts.

Automation Plan Sketch#

env: contexts: - name: app urls: ['https://staging.example.com'] jobs: - type: spider parameters: context: app maxDuration: 5 - type: activeScan parameters: context: app policy: Default Policy

Fail the pipeline when new alert nodes appear at levels you care about. The baseline file doubles as the delta log.

HUD Workflow#

  1. Start the browser from ZAP; the HUD icon toggles panels.
  2. The Sites panel lists the tree; hovering a node shows alerts.
  3. Right-click a request and "Attack" runs an active scan on that branch only.

Limits to Note#

ZAP's alert tuning still needs human triage. False positives from reflected parameter probes are common; a weekly pass over new alerts, plus a suppressions file, keeps the list usable.

ZAP vs Burp on a Real Passive Baseline#

Run the same site through both against a stored baseline. ZAP frequently finds CVEs by template and reports them with a CVE id attached; Burp reports alerts with references and severity. The union of both lists is the sanity check after a migration.

ZAP Marketplace Add-ons#

  • DevWebAlerts: development-specific findings (debug endpoints, source maps).
  • Passive Scanner Rules: cookie flags, security headers, and info leaks.
  • SOAP / XML: request templates for legacy services.

Keep add-ons pinned; a silent update changes the alert set between runs.

Encoding Config#

Request and response encodings sit in File -> Options -> Session Properties. When a target uses a legacy charset, ZAP mis-decodes by default and your payloads hit the wrong bytes. Switch the session charset and re-run.

Docker Mode#

docker run -t owasp/zap2docker-stable zap-baseline.py -t https://target

The baseline image exits nonzero on a defined alert level, which lets CI gate on the result. Tune -I and the alert threshold so the gate is meaningful.

Triage Template#

FieldExample
AlertSQL Injection
ConfidenceMedium
Parameterid
Evidence' OR '1'='1 returned same row count
Next stepVerify with time-based pair

A row per alert with evidence attached is the working state, not a final verdict.

ZAP API#

curl 'http://localhost:8080/JSON/ascan/view/scanProgress/?scanId=0' -H 'X-ZAP-API-Key: $KEY'

The REST API lets you drive a scan from a script. Poll scanProgress then pull alerts/view/alertsByScanId.

Scripting#

ZAP scripts live under File -> Scripts. Passive scan rules can be written in JavaScript or Python and compiled into the scanner. Start from the templates; modifying an existing rule is faster than writing a new one.

Authentication Handling#

Contexts carry auth: login URL, credential placeholders, and a logged-in indicator regex. If the regex stops matching, ZAP reports the scan as logged out and you waste the run. Pick an indicator string that is stable across the session.

Plugin Refresh#

zap.sh -updateaddon

Keep plugins and scripts current; a silent out-of-date add-on reports stale findings.

Report Format#

Export reports in markdown for code review. Each alert row ties the evidence to a site tree node. Reviewers verify faster when evidence is attached to the row.

Baseline vs Full Scan#

The baseline scan is quick, dev-surface only. The full active scan is what you run on staging. Keep the two outputs in separate folders so a regression in the quick set is obvious.

Pipeline Plan#

What a ZAP-in-CI rollout looks like:

  • Baseline scan on every deploy
  • Full active scan on staging weekly
  • Alerts exported and diffed against the prior run
  • New alert levels triaged within a day
  • Suppression file reviewed each month
  • Tutorial captures archived for the new-hire onboarding

Reference Tables#

ModeCadence
BaselineEvery deploy
Full activeWeekly on staging
UpdateAdd-ons pinned monthly

Reminders#

  1. confirm before reporting
  2. confirm before reporting
  3. confirm before reporting
  4. confirm before reporting
  5. confirm before reporting
  6. confirm before reporting
  7. confirm before reporting
  8. confirm before reporting
  9. confirm before reporting
  10. confirm before reporting
  11. confirm before reporting
  12. confirm before reporting
  13. confirm before reporting
  14. confirm before reporting

Command Cheatsheet#

zap.sh -cmd -autorun plan.yaml curl 'http://localhost:8080/JSON/ascan/view/alerts/?baseurl=target'

Final Notes#

  1. confirm, document, report
  2. confirm, document, report
  3. confirm, document, report
  4. confirm, document, report
  5. confirm, document, report
  6. confirm, document, report
  7. confirm, document, report
  8. confirm, document, report
  9. confirm, document, report
  10. confirm, document, report
  11. confirm, document, report
  12. confirm, document, report
  13. confirm, document, report
  14. confirm, document, report
  15. confirm, document, report
  16. confirm, document, report
  17. confirm, document, report
  18. confirm, document, report
  19. confirm, document, report
  20. confirm, document, report

Short Notes#

  1. document the observation, then the conclusion
  2. document the observation, then the conclusion
  3. document the observation, then the conclusion
  4. document the observation, then the conclusion
  5. document the observation, then the conclusion
  6. document the observation, then the conclusion
  7. document the observation, then the conclusion
  8. document the observation, then the conclusion
  9. document the observation, then the conclusion
  10. document the observation, then the conclusion
  11. document the observation, then the conclusion
  12. document the observation, then the conclusion
  13. document the observation, then the conclusion
  14. document the observation, then the conclusion
  15. document the observation, then the conclusion
  16. document the observation, then the conclusion
  17. document the observation, then the conclusion
  18. document the observation, then the conclusion
  19. document the observation, then the conclusion
  20. document the observation, then the conclusion
  21. document the observation, then the conclusion
  22. document the observation, then the conclusion

Scan Modes Compared#

ModeCadenceOwner
BaselineEvery deployDevOps
Full activeWeeklyAppSec
Add-on updateMonthlyAppSec
Alert triageDailyDev

Closing Notes#

  1. Verify each observation with a second independent check.
  2. Prefer packet, request/response, or log evidence over prose.
  3. Tie the finding to the control that should have caught it.
  4. Redact secrets but keep the request shape visible.
  5. Never quote a payload you have not actually tested.
  6. Keep one repro per file; name it clearly.
  7. Update the matrix when a new tool or a new gadget appears.
  8. Shorten CI runs; the tool should fit in a normal deploy.
  9. Confirm a false positive before you report it.
  10. A finding without evidence is folklore.
  11. Document the exact time delta or row count.
  12. Record the binary version or framework version in the report.
  13. Every tool output in the report ties to a command.
  14. The evidence tree should let a second reader replay the finding.
  15. Log the encoding and the raw bytes with the finding.
  16. If a fix closes one probe, re-run the others to be sure.
  17. Closing one instance rarely closes the class.
  18. Rotate pretexts and rate limits so the test keeps signal.
  19. Track report rate, not click rate, for awareness campaigns.
  20. Keep capture files short; slice the interesting window.
  21. ZAP baselines belong in CI, full scans on staging.
  22. Burst the auth endpoint, then verify no lockout.
  23. Diff lockfiles before running a supply-chain claim.
  24. Parameter pollution hides in headers and cookies too.
  25. Checksum your dependencies and rotate keys on a schedule.
  26. Time-based blind is slow; always pair it with a boolean check.
  27. Show the GRANTS output; it proves reachability limits.
  28. DOM sinks are data-flow endpoints, not just payload targets.
  29. Trusted Types and CSP sit on the same defense line.
  30. Stash the tshark JSON slice with the pcap for reference.
  31. A short pcap with notes beats a ten-minute capture.
  32. Name files with date, host, and window.
  33. A flat periodic line in the IO graph is a beacon candidate.
  34. Spike bursts in Burp are usually manual, not scanner.
  35. Tune Nuclei rate limits so the range is not blocked.
  36. sqlmap risk/level flags widen the payload classes.
  37. Arjun finds parameters that do not appear in the URL.
  38. Keep WordPress plugin nonces in a separate test case.
  39. XML-RPC is the slow, quiet way in. Disable it if unused.
  40. Backup files in the docroot are findings by themselves.
  41. Upload extension checks should run on the normalized name.
  42. Homoglyphs hide inside scope lists and allowlists.
  43. Normalize at the edge, log raw, never filter before decode.
  44. UTF-7 and legacy codecs keep bypassing naive filters.
  45. A fullwidth probe that passes is a bug in the pipeline.
  46. Rotate keys, pin versions, and rotate them again after a patch.
  47. Prototype pollution turns one key into a global change.
  48. __proto__ is the first key to block; check constructor too.
  49. Run npm ls deep; the vulnerable path is rarely the top level.
  50. Refuse constructor.prototype keys at every merge point.
  51. Freeze Object.prototype for the server if you must merge.
---
Share this post:

What do you think?

React to show your appreciation

Related Posts