visitor@audit:~$ ./validate --target 127.0.0.1:3000 --report JuiceShop_PenTest_PoC.pdf [+] loaded 65 reported findings [+] re-tested each with a finding-specific oracle (no "HTTP 200 == vuln") [+] evidence redacted · SHA-256 hash-chain verified ==> done.▮
Vulnerability Validation & Discovery
Independent validation of the OWASP Juice Shop penetration-test PoC catalogue — 65 reported findings re-tested against a local Juice Shop v20.3.0 instance, with a supplementary discovery pass.
# verdict summary
# verdict definitions
How each verdict was assigned. A bare HTTP 200/500, a reflected string, or a reachable endpoint was never treated as proof — each verdict rests on a finding-specific oracle.
A valid test reproduced the claimed security behaviour and its impact, with evidence (e.g. decoded admin JWT, cross-user data returned, script executed in the browser).
The documented PoC was executed correctly with the right preconditions, but the claimed impact did not occur or was contradicted by evidence. Sub-classes: Invalid / Flawed PoC (the report's own evidence doesn't support the claim — e.g. #2, where a public version endpoint returning 200 is not an authz bypass), by-design/public, and version-specific (behaved differently on v20.3.0).
No definitive test could be run — because of missing PoC details or an unresolved technical limitation, not lack of effort. Here this applies to exactly one finding, #21 (the PDF captured no request/response and the target identity doesn't exist on v20.3.0).
Used only for the supplementary items (N1/N2): behaviour observed but with an explicit evidence gap (e.g. N1's financial effect unmeasured). These sit outside the original-65 totals.
⚠ Not Reproduced ≠ fixed. It means the claim wasn't demonstrated on this version/configuration under faithful testing.
# findings
// no findings match your filters
# supplementary observations (outside the 65)
N1Negative basket quantity accepted BUSINESS LOGICPARTIAL▸
POST /api/BasketItems accepts a negative quantity (e.g. -50); checkout then
returns an order confirmation. Partially verified — acceptance & successful checkout
observed; the financial/total effect was not measured. Transcript is in-memory, not a saved artifact.
N2Customer can create catalog products AUTHZOBSERVED▸
A non-admin customer can POST /api/Products (HTTP 201, persisted) while DELETE
is admin-gated (401) — a create/delete authorization inconsistency. Intended policy is
not assumed; transcript is in-memory, not a saved artifact.
# methodology · scope · limits
Methodology ▸
- Each finding re-tested with a finding-specific decision rule; an HTTP 200/500, a reflected string, or a reachable endpoint was never proof by itself.
- Tooling: Python
requests, headless Playwright (Chromium) for XSS execution,curl. No commercial scanners. - Disposable accounts/records for state-changing tests.
Scope ▸
- One authorized local instance only:
127.0.0.1:3000. - No external hosts, no off-host redirects, no destructive or high-volume testing.
- Out of scope (not exploited): JWT forgery, XXE file-read, SSRF-to-internal services.
Evidence & version notes ▸
- Request/response artifacts stored with secrets redacted, chained under a SHA-256 ledger — referenced for traceability but not published.
- #12 / #22 required a 10-column UNION on v20.3.0 (report used 9). #41≡#40, #48≡#47 duplicate.
- Not Reproduced ≠ fixed. All results are specific to v20.3.0.
Evidence-quality caveats (#27, N1, N2) ▸
- #27: saved evidence → Not Reproduced; a later unsaved empty-body probe suggested deluxe-without-payment. Discrepancy documented; manual confirmation recommended.
- N1/N2: in-memory transcripts, not saved artifacts; N1's financial effect unmeasured; N2's intended policy not assumed.