Error message leaked via utils.getErrorMessage in checkKeys catch block
The catch block forwards the raw error message to the client via utils.getErrorMessage(error), which returns error.message / String(error) and can leak internal details.
In checkKeys() the catch block returns the result of utils.getErrorMessage(error) directly in the JSON response body:
} catch (error) {
res.status(500).json(utils.getErrorMessage(error))
}
utils.getErrorMessage in this codebase is a thin wrapper that returns error.message for Error instances and String(error) otherwise — it is not a sanitizer that maps known error classes to user-safe messages. As a result, any unexpected exception thrown inside the handler (e.g., from the dynamic import('ethers'), the HDNodeWallet.fromPhrase call, or downstream code) surfaces its raw message — including module paths or library-internal error strings — to the HTTP client. This matches the rule's true-positive criteria: a catch (err) in an HTTP route handler where the response body includes err.message / String(err).
- Send a malformed request to the route bound to
checkKeysthat triggers an exception inside the try block (e.g., causeHDNodeWallet.fromPhraseor an internal call to throw). - Observe the 500 response body — it contains the raw underlying error message instead of a generic message like
{ error: "internal server error" }.
Unauthenticated attackers probing the endpoint can fingerprint internal library behavior, file/module identifiers, and other implementation details from raw error text, aiding further attacks.
The catch block at lines 28-30 literally executes res.status(500).json(utils.getErrorMessage(error)), returning the raw error message to the HTTP client. utils.getErrorMessage in the Juice Shop codebase returns error.message for Error instances, which is not sanitization. Any unexpected exception from HDNodeWallet.fromPhrase or the dynamic import('ethers') would surface internal details to an unauthenticated caller, matching the error-message-leak pattern. The exploit is reachable from untrusted input via the route handler.
The checkKeys route is an HTTP endpoint with no visible authentication middleware, so an unauthenticated remote attacker can reach the catch block by sending a malformed body that triggers exceptions in HDNodeWallet.fromPhrase or the dynamic import('ethers'). The sink (res.status(500).json(utils.getErrorMessage(error))) leaks raw error.message / String(error) strings, giving the attacker partial, low-control disclosure of internal library/module details (Confidentiality: Low). There is no write path or DoS introduced by this bug, so Integrity and Availability are None, and the leak stays within the same component (Scope: Unchanged).
- CWE-209
- CWE-754
- OWASP A05:2021