agentggagentgg
Back to all findings
LOWconfirmederror-message-leakerror-info-leak689bc3efc326

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.

Fileroutes/likeProductReviews.ts
Lines5557
Confidence
85%
File statusvalidated
Details

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.

Proof of concept
  1. Authenticate and call POST to the likeProductReviews route with an id that triggers a driver-level failure on the second findOne/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).
  2. Observe the HTTP 500 response body contains the serialized error object with internal details instead of a generic message.
Impact

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.

Validation
confirmed

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.

CVSS 3.1
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
Base score: 3.1 · LOW

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).

References