Inner catch serializes entire error object in 500 response
The inner catch block returns the raw error object as JSON to the client, leaking internal details from MongoDB driver errors.
In routes/likeProductReviews.ts, the inner try block wrapping the second findOne/update calls catches errors with:
} catch (err) {
res.status(500).json(err)
}
res.json(err) serializes the entire error object — including any enumerable properties the MongoDB driver attaches (error code, command details, etc.) and, depending on how the error is constructed, the message field. This matches the rule's true-positive criteria: a catch block in an HTTP route handler returns a response body that includes the error object directly. There is no sanitization or mapping to a user-safe error, and there is no static fallback like { error: 'internal error' }.
Note the outer catch (line 58) correctly returns a static 'Wrong Params' message — it is the inner catch that leaks.
- Authenticate and call POST to the likeProductReviews route with an
idthat triggers a driver-level failure on the secondfindOne/update(e.g. by causing the document to become malformed between the two calls, or by injecting a value that triggers an internal NeDB/Mongo error after the artificial 150ms sleep). - Observe the HTTP 500 response body contains the serialized error object with internal details instead of a generic message.
Any authenticated user can probe the endpoint to obtain database driver error details (error codes, internal field names, operational hints). This aids attackers in fingerprinting the data layer and crafting follow-on attacks such as NoSQL injection refinement. No special privileges beyond a regular user account are required.
The inner catch at lines 55-57 contains res.status(500).json(err), which serializes the raw error object directly to the response body with no sanitization or static fallback. The exploit path is reachable: an authenticated user POSTs an id, and if the second findOne returns undefined (e.g., review deleted during the 150ms sleep window) the updatedReview.likedBy access throws a TypeError whose message/stack-related enumerable props get leaked; driver-level errors from update would similarly leak Mongo/NeDB internals. The outer catch correctly uses a static 'Wrong Params' string, which highlights the asymmetry. Scope explicitly says to treat findings as production-grade regardless of Juice Shop's training purpose.
The route is reachable over HTTP (AV:N) but the inner catch only fires when the second findOne/update fails after the artificial 150ms sleep — triggering that driver-level error reliably requires preparation/race-style conditions (e.g., mutating the document between the two calls), so AC:H. The handler explicitly rejects unauthenticated requests via security.authenticatedUsers.from(req) returning 401, so any regular user account suffices (PR:L) with no victim interaction (UI:N). The leak (res.status(500).json(err)) exposes limited internal driver metadata — error codes, field names, command hints — which the attacker cannot fully choose, giving C:L; no data is modified and the service stays up (I:N/A:N), and the disclosure stays within the same web app component (S:U).
- CWE-209
- OWASP A09:2021