Skip to content

CandyShop: Open-Source Security Tool Benchmark 2026

Suphi Cankurt

Written by Suphi Cankurt

CandyShop: Open-Source Security Tool Benchmark 2026
Key Takeaways
  • Container scanners produced the most findings by far. DVWA alone: 2,097 from Grype, 1,575 from Trivy โ€” mostly outdated base image dependencies.
  • The earlier F1 ranking is retained below as a withdrawn calculation, not a validated comparison of scanner accuracy.
  • Cross-tool agreement does not establish true positives or a false-positive rate. The archived findings still require independent triage.
  • ZAP and Nuclei recorded fewer findings than the container scanners; their different input scopes prevent a direct accuracy ranking.

The CandyShop benchmark records output from 12 tools in five categories โ€” SAST, DAST, SCA, container scanning, and IaC โ€” across 6 intentionally vulnerable applications (OWASP Juice Shop, Broken Crystals, Altoro Mutual, vulnpy, DVWA, and WebGoat).

The archived table contains 10,047 finding records. Raw outputs, exact versions and final triage files are not preserved, so the run cannot be independently reproduced from this repository. The prior precision, recall and F1 calculations are withdrawn as accuracy evidence; the finding counts remain available below.

Key Findings#

1. Container-image findings dominate this snapshot#

DVWA’s PHP/Apache image produced 3,672 container findings (Grype + Trivy combined). Juice Shop’s Node.js image: 271.

These are different applications and dependency sets, so this comparison does not isolate base-image choice as the sole cause. It does show why operating-system packages deserve attention when reviewing a container scan.

Base image matters more than code: DVWA PHP/Apache image produced 3,672 container findings (Grype 2,097 + Trivy 1,575, 327 critical CVEs) versus Juice Shop Node.js image with only 271 findings โ€” same tools, same configuration

2. More findings does not mean better detection#

Grype reported 5,046 findings across all 6 targets โ€” the highest count from any tool. The vast majority came from base image OS packages, not application-level flaws. npm audit found 99 findings total, but 9 were critical and 46 were high. Look at severity distribution, not totals.

3. No single scanner catches everything#

Scanners operate on different inputs and can leave different gaps. The saved data cannot quantify how much each tool missed; choose complementary tools by coverage needs and verify their findings independently.

4. Container scanners and SCA tools inspect different inputs#

Trivy and Grype inspect container packages, while npm audit and pip-audit focus on application dependencies. On Juice Shop, Trivy recorded 135 findings and npm audit 56. Counts alone do not reveal overlap between those findings.

5. DAST coverage depends on authentication#

ZAP consistently found 5-20 issues per target, mostly medium or lower severity. Without login credentials, ZAP only tests what an anonymous visitor can reach. The gap between 13 findings on Juice Shop and 20 on DVWA says more about how deep the login wall sits than about actual vulnerability counts.

6. IaC scanning adds configuration checks#

Checkov flagged Dockerfile misconfigurations across 3 targets (Juice Shop, vulnpy, DVWA). Running containers as root, skipping health checks โ€” these aren’t “vulnerabilities” in the traditional sense, but they’re real security problems that SAST, SCA, and DAST tools all ignore.


What Do the Archived Scores Show?#

The previous calculation labeled 654 cross-tool matches as true positives. Matching reports are a review signal, not independent ground truth. The following table preserves those old calculations for transparency; it must not be used to rank detection quality.

Precision was forced to 1.000 by leaving unconfirmed findings out of the false-positive denominator. Without independent labels and the original triage records, neither the reported recall nor F1 can be validated.

Withdrawn consensus calculations โ€” not validated scanner accuracy
ToolAvg F1PrecisionRecallTPFPCWEs
Trivy0.7831.0000.662309025
FindSecBugs0.7071.0000.5716207
OpenGrep0.6451.0000.490109013
Bandit0.6251.0000.4551004
Grype0.5281.0000.3829205
Dependency-Check0.4001.0000.26327010
npm audit0.3941.0000.24619010
OWASP ZAP0.2601.0000.1642006
Nuclei0.0901.0000.048300
NodeJsScan0.0771.0000.040301

How Do Different Scanner Categories Compare?#

The charts now show the recorded finding counts from the heatmap below. They compare output volume within each category. For accuracy testing, the OWASP Benchmark illustrates the need for labeled expected results; agreement between scanners is not a substitute.

5 scanner categories with different blind spots: SAST catches source code patterns, DAST finds runtime issues but needs auth, SCA covers app dependencies, container scanning covers full OS+app image with high volume, IaC scanning catches Dockerfile misconfigs uniquely

How to read these charts:

  • Finding-count chart (above) shows all 12 tools using their recorded totals, not withdrawn F1 values.
  • Category charts use the same counts for tools with similar input scopes. A longer bar means more output records, not better detection.
  • pip-audit and Checkov remain in the overall chart and heatmap. Their records should not be discarded because they lack a matching report from another category.

SAST Tools#

FindSecBugs recorded 192 findings across 2 Java targets. OpenGrep recorded 456 across all 6 targets; the different language and target coverage matters when comparing volume.

Bandit recorded 87 findings on vulnpy; NodeJsScan recorded 14 across the two JavaScript targets. The archive does not establish their false-positive rates.

Container Scanners#

Trivy recorded 3,854 findings and Grype 5,046. Both inspect packages inside container images; their totals do not tell us which scanner was more accurate.

SCA Tools#

Dependency-Check recorded 137 findings across its applicable targets, npm audit 99 across the JavaScript targets, and pip-audit 14 on vulnpy. Their ecosystems differ, so a total is not an interchangeable measure of coverage.

DAST Tools#

ZAP recorded 83 findings and Nuclei 57. Crawl configuration, templates and authentication affect DAST coverage; the archived totals do not establish a winner.

IaC Scanning#

Checkov is the only IaC tool in the benchmark. It flagged Dockerfile misconfigurations in 3 targets (Juice Shop, vulnpy, DVWA) โ€” running containers as root, missing health checks, using latest tags.

Checkov recorded 8 findings across those targets. Its IaC scope differs from source, dependency and runtime scanning; the overall chart includes its output without treating cross-tool agreement as a validity test.


How Many Findings Did Each Tool Record?#

The heatmap below preserves total finding records per tool and target. Darker red means more records, not more unique or confirmed vulnerabilities. The expandable notes reproduce observations from the archived page; their severity and root-cause details cannot be independently checked without the raw reports.

ToolJuice ShopBroken CrystalsAltoro MutualvulnpyDVWAWebGoatTotal
Grype1362,111621442,0974965,046
Trivy1351,555501361,5754033,854
OpenGrep70424612100186456
FindSecBugsโ€”โ€”54โ€”โ€”138192
Dep-Check066230147137
npm audit5643โ€”โ€”โ€”โ€”99
Banditโ€”โ€”โ€”87โ€”โ€”87
ZAP1351714201483
Nuclei141212510457
Checkov3002308
pip-auditโ€”โ€”โ€”14โ€”โ€”14
NodeJsScan113โ€”โ€”โ€”โ€”14

โ€” = tool not applicable to this target's language/framework. Color scale: 0โ€“10 11โ€“50 51โ€“200 201โ€“500 501โ€“1000 1000+

OWASP Juice Shop โ€” 428 total findings across 8 tools
  • OpenGrep found 70 issues with 38 at high severity โ€” the only SAST tool to flag high-severity vulnerabilities on Juice Shop.
  • Grype and Trivy reported nearly identical totals (136 vs 135) with similar severity distributions, which is reassuring โ€” the two container scanners largely agree.
  • npm audit found 7 critical and 31 high-severity dependency vulnerabilities.
Broken Crystals โ€” 3,847 total findings across 8 tools
  • Grype produced 2,111 findings โ€” the heaviest base image in the benchmark, with 30 critical and 511 high-severity issues.
  • Trivy hit 1,555 findings. The bloated base image explains the jump from Juice Shop’s 135.
  • OpenGrep found 42 issues (26 high severity), while NodeJsScan caught 13 including 10 high-severity findings (hardcoded credentials and eval injection).
  • Dependency-Check found 66 issues versus zero on Juice Shop โ€” richer dependency trees give it more to work with.
  • ZAP found only 5 issues despite 20+ vulnerability types in the target. Without authentication, DAST tools just can’t reach enough of the attack surface.
Altoro Mutual โ€” 264 total findings across 7 tools
  • FindSecBugs led with 54 findings, including 10 SQL injection, 3 path traversal, and 1 XXE. This is the only target where a Java-specific SAST tool outperformed container scanners.
  • OpenGrep found 46 issues (13 high, 33 medium), picking up source-level patterns that FindSecBugs missed.
  • Trivy reported 50 container findings including 5 critical CVEs in the Java runtime layer.
  • ZAP recorded 17 findings here, compared with 20 on DVWA. The totals alone do not explain differences in crawl coverage.
vulnpy โ€” 414 total findings across 8 tools
  • Bandit is the only Python-specific SAST scanner in the benchmark. It found 87 informational issues โ€” mostly eval(), exec(), and subprocess usage.
  • Trivy found 136 container vulnerabilities, 107 of them low severity. The Python base image has a moderate vulnerability surface.
  • pip-audit found 14 medium-severity issues โ€” a clean, focused set compared to the container scanning noise.
  • Interesting coincidence: ZAP and pip-audit both returned 14 findings, from completely different angles (runtime vs dependency analysis).
DVWA โ€” 3,806 total findings across 7 tools
  • One of the highest-volume targets in the archived notes. Grype alone reported 2,097 findings and Trivy added 1,575. The PHP/Apache base image is a CVE magnet โ€” 327 critical findings from Grype.
  • Nuclei found a critical-severity issue here โ€” the only critical from any DAST tool across all 6 targets. An exposed admin panel / known vulnerable endpoint.
  • Dependency-Check found only 1 medium-severity issue. PHP/Composer gets much less SCA coverage than npm or Maven.
WebGoat โ€” 1,288 total findings across 7 tools
  • OpenGrep found 186 issues โ€” the highest SAST count in the benchmark. The Java/Spring codebase triggered 44 high-severity and 142 medium-severity findings.
  • FindSecBugs found 138 issues, including 14 SQL injection, 19 path traversal, and 14 Spring CSRF findings. Its bytecode analysis catches patterns that source-level scanners miss.
  • Grype (496) and Trivy (403) had similar severity distributions here too โ€” container scanners agree consistently.
  • Dependency-Check had its best result here with 47 issues. Java/Maven is the ecosystem it handles best.

What Tools and Targets Are in the Benchmark?#

Tools Tested#

The CandyShop benchmark tests 12 open-source tools across five categories: SAST (OpenGrep, NodeJsScan, Bandit, FindSecBugs), DAST (OWASP ZAP, Nuclei), SCA (npm audit, pip-audit, OWASP Dependency-Check), container scanning (Trivy, Grype), and IaC (Checkov). All use open-source licenses (Apache 2.0, MIT, LGPL, GPL) โ€” no commercial scanners, no vendor agreements needed.

CategoryTools Tested
SASTOpenGrep, NodeJsScan, Bandit, FindSecBugs
DASTOWASP ZAP, Nuclei
SCAnpm audit, pip-audit, OWASP Dependency-Check
ContainerTrivy, Grype
IaCCheckov

Test Targets#

6 intentionally vulnerable applications spanning Node.js, Java, Python, and PHP:

TargetStackVulnerabilitiesNotes
Juice ShopNode.js/Express/Angular100+ challengesMost widely used vulnerable app
Broken CrystalsNode.js/TypeScript40+ typesJWT flaws, XXE, business logic
Altoro MutualJ2EEClassic web vulnsSQL injection, XSS, path traversal
vulnpyPython/Flask13 categoriesPython-specific scanner testing
DVWAPHP/MariaDBAdjustable levelsClassic training ground
WebGoatJava/SpringGuided lessonsOWASP teaching application

The original notes describe Docker Compose and default scanner settings. The saved repository lacks a complete version/configuration manifest, so that setup cannot be verified or reproduced exactly.


How Is the Benchmark Methodology Designed?#

Environment Setup#

The original setup used Docker Compose. The surviving Compose file does not include all six target services or all referenced build contexts, and the scanner versions and commands were not preserved.

Tool Selection Criteria#

The original selection notes listed three intended requirements; the archive does not preserve a version-by-version checklist:

  1. Open-source license (Apache 2.0, MIT, LGPL, GPL, or similar). No commercial tools, no freemium tiers, no “community editions” with half the features stripped out.
  2. Active maintenance โ€” last commit within the past 12 months.
  3. CLI-driven โ€” can run headless in a CI pipeline without a GUI.

How Is Ground Truth Established?#

The earlier multi-tool consensus model treated matching CWE/location reports from two tools as true positives. That assumption does not establish ground truth: tools can agree on a false positive, and category-specific findings may have no second scanner to confirm them.

Single-tool findings can be valid. The previously reported 152-entry reference set and its final triage decisions are not preserved, so the old counts cannot be independently validated.

Agreement can help prioritize triage, but it cannot prove precision or supply the missing false negatives. The old model could both exclude real issues and accept shared false positives.

How Is F-Measure Calculated?#

F-measure (F1 score) is the harmonic mean of precision and recall. The standard formulas are:

  • Precision = TP / (TP + FP) โ€” how many of the tool’s confirmed findings are real
  • Recall = TP / (TP + FN) โ€” how many of the known ground-truth issues the tool detected
  • F1 Score = 2 * (Precision * Recall) / (Precision + Recall)

The old calculation excluded unconfirmed findings from FP and therefore reported precision of 1.000. That is a property of the calculation, not evidence that every finding was correct.

The preserved score table is historical only. A new accuracy comparison would need versioned targets, independent expected-result labels, complete scanner output and adjudication of every relevant finding.

What these numbers can’t tell you#

The archived counts cannot establish precision, recall, a false-positive rate, or a lower bound on coverage. Their useful scope is comparing recorded output volume across tools and targets.

The snapshot covers six deliberately vulnerable applications. Its finding counts do not predict what a current tool will find in your production stack.


Related guides:

Frequently Asked Questions

What is the CandyShop benchmark?
CandyShop preserves aggregate results from 12 security tools across 6 vulnerable applications. The saved table contains 10,047 records, but the raw output and version manifest needed for exact reproduction are not preserved.
How many tools and targets are included in the 2026 benchmark?
The 2026 benchmark tests 12 open-source tools (OpenGrep, NodeJsScan, Bandit, FindSecBugs, OWASP ZAP, Nuclei, npm audit, pip-audit, OWASP Dependency-Check, Trivy, Grype, and Checkov) against 6 vulnerable applications (Juice Shop, Broken Crystals, Altoro Mutual, vulnpy, DVWA, and WebGoat).
Why are only open-source tools included?
The project selected tools available without commercial scanner licenses. That makes the tooling accessible, but does not make this archived run reproducible without its versions, configurations and raw output.
How is accuracy measured in this benchmark?
The previous model used cross-tool agreement to label true positives. That is not independent ground truth, so the earlier precision, recall and F1 results are withdrawn as accuracy evidence.
Which tool had the highest accuracy score?
The archive cannot identify the most accurate tool. Its old F1 table is retained as a withdrawn calculation; the active charts show recorded finding counts instead.
Why do container scanners find so many more vulnerabilities than other tool types?
Trivy and Grype scan every package in a Docker image โ€” OS layer and application dependencies. A single outdated base image (like DVWA’s PHP/Apache image) can have hundreds of known CVEs in system libraries that application-level scanners never look at.
Can I reproduce these benchmark results?
Not exactly from the surviving repository. It preserves aggregate counts and partial setup notes, but lacks the raw scanner output, version manifest, commands and final triage records.
What is the best open-source SAST tool?
This snapshot cannot establish a best SAST tool. Use language support, integration requirements and a representative evaluation repository to build a shortlist; archived output counts do not measure detection quality.
How does Trivy compare to Grype for container scanning?
The archived table records 3,854 findings for Trivy and 5,046 for Grype. Different output counts do not establish which tool has better precision, recall or coverage.
What percentage of security scanner findings are false positives?
No defensible percentage can be calculated from this archive. Findings reported by only one scanner are not automatically false, and agreement between scanners does not automatically make a finding true.
Suphi Cankurt

Written & maintained by

Suphi Cankurt

Eight years on the vendor side of application-security sales โ€” thousands of evaluations and demos. I started AppSec Santa in 2022 to put that insider view to work for buyers. Independent of any vendor, paid by none, and honest about what fits whom.