Raw error message returned in 500 response from review creation
The catch block sends utils.getErrorMessage(err) — which extracts the underlying error's message — directly to the HTTP client, leaking internal/database error details.
In routes/createProductReviews.ts, the catch block at lines 30–32 returns the result of utils.getErrorMessage(err) as the JSON body of a 500 response:
} catch (err: unknown) {
return res.status(500).json(utils.getErrorMessage(err))
}
utils.getErrorMessage is the standard helper used across this codebase to coerce an unknown error to its .message string (it returns err.message when err is an Error, and String(err) otherwise). The result is forwarded verbatim to the client with no sanitization, mapping to known error classes, or replacement with a static message.
Because reviewsCollection.insert is a MongoDB/NeDB operation, the raw error string can disclose driver-level details such as duplicate-key violations, schema/validation messages, BSON parse errors, or internal field names — useful fingerprints for attackers probing the data layer.
This matches the criteria: a catch block in an HTTP route handler whose response body includes err.message (via the trivial getter), with no log-and-generic-response or sanitized-error-mapping pattern in place.
- Send a POST request to the product review endpoint with a payload crafted to trigger a backend error (e.g., an invalid
productid format, a duplicate insert, or a malformedmessagevalue that fails validation in the underlying collection). - Example:
POST /rest/products/abc/reviews with body {"message": <object that violates collection constraints>, "author": "a@b.c"}.
- Observe the 500 response body — it contains the raw driver error text (e.g., index/constraint information or internal field names) instead of a generic message.
Unauthenticated clients can elicit verbose backend error strings from the review-creation endpoint, exposing database driver behavior, schema/field hints, and other internal details that help reconnaissance and follow-on attacks. No authentication is required to receive the leaked text.
The catch block at lines 30-32 directly forwards utils.getErrorMessage(err) (which returns err.message) as the JSON body of a 500 response with no sanitization or mapping. Since reviewsCollection.insert is a NeDB/MongoDB operation, malformed input (e.g., invalid product id, constraint violation) would surface driver-level error text to an unauthenticated client. The route is reachable via POST and has no input validation prior to the insert, so attacker-controlled payloads can reliably trigger leaky errors. Per the scope rules, this should be judged as a real production bug.
The endpoint POST /rest/products/:id/reviews is reachable over the network with no authentication check in the handler (no security.isAuthorized() guard surrounds the route, and security.authenticatedUsers.from(req) is only used for an unrelated challenge solver), so AV:N/PR:N/UI:N. Triggering the leak only requires sending a malformed payload to cause reviewsCollection.insert to throw, which is low-complexity (AC:L). The impact is limited to disclosure of backend/driver error strings via utils.getErrorMessage(err) — useful reconnaissance fingerprints but attacker doesn't control which sensitive data leaks, so C:L and I:N/A:N with Scope unchanged.
- CWE-209: Generation of Error Message Containing Sensitive Information
- CWE-754: Improper Check for Unusual or Exceptional Conditions
- OWASP API8:2023 Security Misconfiguration