Operator/object injection via JSON.parse() of route parameter into Sequelize where clause
`getRecycleItem` runs `RecycleModel.findAll({ where: { id: JSON.parse(req.params.id) } })`, letting an attacker substitute the scalar id with arbitrary JSON (objects, arrays, operator hashes) and influence the resulting query semantics.
Lines 12–16 of routes/recycles.ts:
RecycleModel.findAll({
where: {
id: JSON.parse(req.params.id)
}
})
The brief's true-positive pattern "JSON.parse(req.body.*) as a query argument" applies directly: whatever JSON the caller supplies becomes the id selector. Although the underlying store is SQL (Sequelize), the JSON.parse hop allows the attacker to smuggle non-scalar values into the where clause:
/api/Recycles/[1,2,3]becomesWHERE id IN (1,2,3)— pulls records the user shouldn't see./api/Recycles/{"$gt":0}or/api/Recycles/{"gt":0}(depending on Sequelize version) maps to operator semantics returning every recycle row.- Object payloads crash the DB layer in ways that leak SQL/Sequelize stack traces (this is the documented Juice Shop "REST API" / "JSON" injection challenge).
The correct shape is to coerce: id: Number(req.params.id) (and 400 on NaN). There is no coercion or schema validation between the request and the query.
GET /api/Recycles/%7B%22%24gt%22%3A0%7D (URL-encoded {"$gt":0}) — unauthenticated. The server JSON-parses the param and passes the resulting object as where.id, returning all recycle rows rather than the single requested record.
Unauthenticated horizontal authorization bypass / data exposure: an attacker can enumerate or dump the entire Recycle table by sending a JSON object instead of a numeric id. Malformed payloads also leak Sequelize error stack traces.
The code literally passes JSON.parse(req.params.id) into where: { id: ... } with no coercion, schema validation, or auth check in this handler. An attacker can supply a JSON array ([1,2,3]) or operator object that Sequelize will interpret as an IN/operator filter, returning rows beyond the intended single id — this is the canonical Juice Shop "REST API JSON injection" pattern. The catch block also discards the underlying error, but pre-parse failures still leak via crashes/errors. Exploit chain (untrusted route param → JSON.parse → ORM where clause) is reachable and matches the detector's PoC.
The sink is a plain Express GET route (getRecycleItem) with no authentication or authorization middleware visible in the file, so an unauthenticated remote attacker can hit /api/Recycles/... directly (AV:N, PR:N, UI:N, AC:L). Supplying a JSON operator object (e.g. {"$gt":0}) for req.params.id causes RecycleModel.findAll to return rows the attacker should not see, disclosing data from the Recycle table — but the bug is confined to that single read-only findAll against one model, so impact stays within the app (S:U), there is no write/update path (I:N), and the .catch swallows errors so no meaningful DoS is demonstrated (A:N). Confidentiality is rated L rather than H because disclosure is limited to the Recycle table contents, not the entire datastore or arbitrary records of the attacker's choosing.
- CWE-943
- CWE-89
- OWASP API8:2023 Security Misconfiguration