TARGET OWASP Juice Shop · localhost:3000 ·
RAN 16 Aug 2026 · RUN juice-shop-89d8
CriticalOverall posture
20Proven findings
2Critical
8High
10Medium
10/10Classes run
681Agent steps
An autonomous adversary attacked this application across the ten certified attack
classes and proved 20 findings. The authentication and authorization layers are
fundamentally broken: multiple unauthenticated paths lead directly to full administrative
control and remote code execution. Every finding below is a reproduced exploit — not a
guess, a maybe, or a scan result. You can re-run every one of them yourself.
The loop
01 · Prove
Done — 20 findings proven, each with its runnable exploit.
02 · Fix
In this report — a clear remediation for every finding. We never touch your code.
03 · Verify
Re-run after you ship. The proof is that the attack now fails — verified, and dated.
Sensitive file disclosure via /ftp + null-byte bypass
GET /ftp/:file
CWE-552
Open
Medium
PATH
Local File Read via layout param
POST /dataerasure
CWE-22
Open
Medium
IDOR
IDOR — cross-user basket-item tampering
/api/BasketItems/:id
CWE-639
Open
Medium
IDOR
IDOR — read another user's full basket
GET /rest/basket/:id
CWE-639
Open
Medium
IDOR
IDOR — address ownership hijack
PUT/DELETE /api/Addresss/:id
CWE-639
Open
Medium
IDOR
IDOR — recycle-record disclosure + pickup abuse
GET/POST /api/Recycles/:id
CWE-639
Open
Medium
IDOR
IDOR — rewrite another user's product review
PATCH /rest/products/reviews
CWE-639
Open
Medium
SSRF
SSRF — profile image URL fetch
POST /profile/image/url
CWE-918
Open
Medium
XSS
DOM-based XSS — javascript: iframe injection
GET /#/search?q=
CWE-79
Open
Medium
XSS
Stored XSS — username executes on /profile
POST /profile
CWE-79
Open
Baseer · provable securityReport ID juice-shop-89d8 · Page 1
BASEERTrust package · OWASP Juice Shop
What we ran — the certified ten
Every test is the same ten attack classes,
tried the way a real adversary would. This run: all ten hit — each class produced at least one
proven finding.
SQLiproven
XSSproven
IDORproven
AUTHproven
RCEproven
SSRFproven
SSTIproven
EXPOSUREproven
PATHproven
UPLOADproven
Scope & methodology
What we tested
The application end to end: login and sign-up, the API behind it, checkout, uploads, and the
data those reach — the whole depth an attacker moves through. Target: OWASP Juice Shop
(a deliberately vulnerable demo app, used with permission as our labeled showcase).
How
An autonomous adversary, run across the ten certified attack classes — ~35 minutes,
681 agent steps. Nothing is reported unless an exploit ran and reproduced: proof,
not prediction. Triage happened by running, never by guessing.
Out of scope — and why
Infrastructure (network, host, cloud configuration) and the long tail of exotic attack classes.
Those are a different test. An honest boundary is a feature, not a gap — we say exactly what we
covered, and the report never overclaims it.
What this report does not claim
The boundary
Known classes, not zero-days. We try the ten certified classes thoroughly. We do not claim we found everything that exists.
Not a guarantee. A pass where nothing proved would mean we couldn't break in on this pass, against these ten — a result, not a promise.
Re-scanning is the truth keeper. Every release changes the answer. This report is true as of the date above, no longer.
How to read it
Every finding is reproducible. Run it yourself — that is the whole difference between this and a scan.
Two times, honestly. The real run took ~35 minutes. Reading this report takes minutes.
Status is honest. "Open" means proven and not yet re-verified after a fix. We never say "fixed" — we re-attack.
Start here — the highest-impact fixes
1 · Fix the login. Parameterized queries everywhere — the auth bypass and the full database dump both disappear.
2 · Verify tokens with a real signature. An unsigned JWT handing out admin is a broken door, not a bug.
3 · Enforce ownership server-side. Every IDOR on this page is one missing check. 4 · Close the open doors — debug panels, default credentials, the /ftp share. Each remediation, with the reproduction proof for its finding, ships with this report.
After you ship
Apply the fixes, then run the same attacks again. The proof a fix worked is that
the attack now fails — verified, and dated. That re-verification is what turns this page from a diagnosis into a defensible
posture you can put in front of an investor, a customer, or a regulator.
Two findings hand over the entire application to an unauthenticated attacker.
Both are the same disease, twice: the server trusts the client. Fix these first.
Critical
01 · SQL Injection — authentication bypass
POST /rest/user/login · CWE-89
What we proved. The login lookup is built from the input string. An unauthenticated
attacker bypasses the password check entirely and authenticates as the built-in
administrator — the server returns a valid, signed session token carrying
role:admin.
Why it matters. Full administrative control without a single credential: user
management, every order and basket, the configuration. One input field hands over the
whole application.
Remediation. Parameterized queries, everywhere — build the query from
data, never from the input. Re-verify: the bypass attack now fails.
Critical
02 · Unsigned JWT accepted — token forgery
GET /api/Users · CWE-347
What we proved. The API accepts a token whose algorithm header claims
none and carries no signature. An attacker forges a token asserting the
administrator's identity, with no secret.
Why it matters. Identity becomes whatever you claim. The forged token lists all
35 accounts, reads the administrator's saved payment cards, and modifies or deletes any
user — a full takeover from a blank page.
Remediation. Verify the signature of every token against the real
secret and reject alg:none outright. Re-verify: the forged token is refused.
Baseer · provable securityReport ID juice-shop-89d8 · Page 3
BASEERTrust package · findings
Findings — high
Eight findings that read secrets, execute code, or hand over data without
breaking anything first. Each is proven — you can reproduce every one.
High
03 · Remote code execution through the template engine
POST /profile · CWE-94
What we proved. A template expression planted in the username field is evaluated
server-side. The expression executes on the machine.
Why it matters. Full code execution on the host — secrets, the database, other
services, anything the server user can reach.
Remediation. Never evaluate user-supplied input in templates — data
and code stay separate. Re-verify: the expression no longer executes.
High
04 · User records and password hashes exposed
GET /rest/memories · CWE-522
What we proved. One unauthenticated request to the photo-wall endpoint returns the
complete user table: emails, roles, password hashes, tokens, and last-login IPs.
Why it matters. Every account is exposed, and MD5 hashes fall to trivial cracking
(the administrator's is admin123). Credential reuse then spreads the breach beyond
this app.
Remediation. Strip sensitive fields from public responses; store
passwords with a slow, salted hash. Re-verify: the dump returns nothing sensitive.
High
05 · SQL Injection — full database dump
GET /rest/products/search · CWE-89
What we proved. The search parameter is concatenated into a SQL query. A UNION
append reads arbitrary rows from any table.
Why it matters. The complete user table — emails and password hashes — exfiltrated
through a search box, unauthenticated.
Remediation. The same parameterization discipline as finding 01.
Re-verify: the union returns no extra rows.
High
06 · Broken access control — any user manages all accounts
GET /api/Users · CWE-862
What we proved. The user-management endpoints are not role-gated. A low-privilege
token reads, modifies, and deletes any user record.
Why it matters. Every account is manageable by any logged-in user — and next to the
JWT flaw, that is full administrative reach.
Remediation. Enforce roles server-side on every user-management route.
Re-verify: the low-privilege token is refused.
High
07 · Mass assignment — unauthenticated admin registration
POST /api/Users · CWE-915
What we proved. The registration endpoint trusts a role field supplied by the
client. One request creates an account with role:admin.
Why it matters. A persistent administrator identity, created in a single request,
no credentials needed — a backdoor that outlives every fix to login.
Remediation. Allow-list the fields a request may set; never accept a
role from the client. Re-verify: the role is ignored.
High
08 · Default administrator credentials
POST /rest/user/login · CWE-798
What we proved. The publicly documented default password still authenticates the
built-in administrator.
Why it matters. The single most common way in. Anyone who reads the documentation
is the administrator.
Remediation. Rotate and disable default credentials; enforce a
password policy. Re-verify: the default is refused.
High
09 · XXE — unauthenticated arbitrary file read
POST /file-upload · CWE-611
What we proved. The XML parser resolves external entities. A crafted document reads
arbitrary files from the server, unauthenticated.
Why it matters. Server files — system users, configuration, keys — read through the
upload handler.
Remediation. Disable external entities in the XML parser.
Re-verify: the crafted document reads nothing.
High
10 · Stored XSS via ZIP-slip file write
POST /file-upload · CWE-79
What we proved. Archive entries are written outside the intended directory. An
attacker plants attacker-controlled HTML into the served webroot.
Why it matters. Stored XSS on every visitor — the planted file is served to anyone
who loads the page. A foothold that spreads.
Remediation. Validate archive entry paths; never write outside the
upload directory; serve uploads inert. Re-verify: the planted file no longer executes.
Baseer · provable securityReport ID juice-shop-89d8 · Page 4
BASEERTrust package · findings
Findings — medium
Ten findings of cross-user access, disclosure, and input mishandling.
None needs a break-in; all are proven.
Medium
11 · Sensitive file disclosure via /ftp
GET /ftp/:file · CWE-552
What we proved. The share lists sensitive files, readable unauthenticated; a
null-byte trick downloads them past the extension filter.
Why it matters. The coupon-encryption bytecode is readable and disassembles to
reveal the scheme — the coupon system's integrity collapses.
Remediation. Remove public access to the share; serve files through
code, not static paths. Re-verify: nothing sensitive is reachable.
Medium
12 · Local file read via layout parameter
POST /dataerasure · CWE-22
What we proved. The layout parameter reaches the filesystem unchecked; a traversal
reads the start of any readable file.
Why it matters. Any authenticated user can peek inside server files — a stepping
stone to the rest.
Remediation. Validate and restrict the path server-side.
Re-verify: traversal returns nothing.
Medium
13 · IDOR — cross-user basket-item tampering
/api/BasketItems/:id · CWE-639
What we proved. Basket items are keyed by id with no ownership check. One account
enumerates, modifies, and deletes another user's items.
Why it matters. Any basket is editable by anyone — cart contents, quantities, and
order values can be inflated or deflated.
Remediation. Check ownership server-side on every object access.
Re-verify: another account's items are refused.
Medium
14 · IDOR — read another user's full basket
GET /rest/basket/:id · CWE-639
What we proved. The basket endpoint trusts the client for ownership. A victim's
basket id returns its full contents.
Why it matters. Basket contents, quantities, coupon state, and owner mapping —
disclosed.
Remediation. Bind the basket to the session, never the client id.
Re-verify: foreign baskets are refused.
Medium
15 · IDOR — address ownership hijack
PUT/DELETE /api/Addresss/:id · CWE-639
What we proved. Saved addresses are keyed by id with no ownership check. Account A
modifies and deletes account B's address.
Why it matters. Full name, mobile, and street of any user — disclosed and mutable.
Remediation. An ownership check on every address operation.
Re-verify: foreign addresses are refused.
Medium
16 · IDOR — recycle-record disclosure and pickup abuse
GET/POST /api/Recycles/:id · CWE-639
What we proved. Recycle records are keyed by id with no ownership check. Cross-user
records are read, and pickups raised against addresses that never asked.
Why it matters. Another user's records disclosed; unsolicited pickups booked at
their address.
Remediation. Ownership checks on both read and write.
Re-verify: cross-user records are refused.
Medium
17 · IDOR — rewrite another user's product review
PATCH /rest/products/reviews · CWE-639
What we proved. A review id is mutable across users. One account silently rewrites
another's review — "MODIFIED BY ALICE — original bob text gone."
Why it matters. Reviews are a trust signal; rewriting them poisons them — a
defacement with a business cost.
Remediation. Bind reviews to their author; reject cross-user patches.
Re-verify: the rewrite is refused.
Medium
18 · SSRF — profile image URL fetch
POST /profile/image/url · CWE-918
What we proved. The image feature fetches a user-supplied URL server-side. The
server reached its own loopback API.
Why it matters. Internal services that were never meant to face the internet become
reachable through the app.
Remediation. Block private ranges at the fetch boundary; don't
follow user-supplied URLs. Re-verify: the internal fetch fails.
Medium
19 · DOM-based XSS
GET /#/search?q= · CWE-79
What we proved. The search page reflects input into a scriptable sink; a crafted
URL executes attacker code.
Why it matters. Attacker JavaScript runs in a visitor's session — and the session
token sits in a non-HttpOnly cookie. Session theft.
Remediation. Escape on output; mark the session cookie HttpOnly and
Secure. Re-verify: the injected code no longer fires.
Medium
20 · Stored XSS — username
POST /profile · CWE-79
What we proved. The profile page renders the username unescaped. A script stored in
the name fires for every visitor to the page.
Why it matters. Persistent attacker code on a page other users load — a watering
hole inside the app.
Remediation. Escape all server-rendered user input; set a strict
CSP. Re-verify: the stored script no longer executes.
Baseer · provable securityReport ID juice-shop-89d8 · Page 5
BASEERTrust package · remediation
The order to fix things — highest impact first
1 · Stop trusting the client for identity. Parameterized queries (findings 01, 05) and real
token verification (02) collapse half the report: the auth bypass, the database dump, the forged
admin, the mass-assignment backdoor, the broken access control. 2 · Kill the defaults and the open doors. Rotate default credentials (08), close the /ftp
share and the debug surface (11), remove sensitive fields from public responses (04). 3 · Enforce ownership server-side. One missing check is the whole IDOR family (13–17):
baskets, addresses, records, reviews. 4 · Harden the input channels. Templates and XML must never evaluate user input (03, 09);
uploads are validated by content, not extension, and served inert (10); escape on every output
path (19, 20); block internal fetches (18); validate paths (12).
After you ship — verification
Apply the fixes, then we run the same attacks
again. The proof a fix worked is that the attack now fails — verified, and dated. That
re-verification is what turns this page from a diagnosis into a posture you can defend. A grade
is issued when the loop closes, never before.
What we don't claim
The boundary
Known classes, not zero-days. We tried the ten certified classes thoroughly. We do not claim we found everything that exists.
Not a guarantee. A pass where nothing proved would mean we couldn't break in on this pass, against these ten — a result, not a promise.
Re-scanning is the truth keeper. Every release changes the answer. This report is true as of the date on page one, no longer.
How to read it
Every finding is reproducible. Run it yourself — that is the whole difference between this and a scan.
Two times, honestly. The real run took ~35 minutes. Reading this report takes minutes.
Status is honest. We never say "fixed." We re-attack, and the attack now fails — verified, and dated.