Users should see a generic error message, and the details should go to your server logs. In review, check that stack traces, SQL errors and file paths never reach the response, that a global handler covers unexpected failures, and that status codes are used correctly.
What the guidance says
The OWASP Error Handling Cheat Sheet recommends returning a generic message to the user, with content that does not reveal implementation details, and recording full details on the server for investigation. It also recommends one catch-all error handler configured in the runtime or in code, so unexpected errors are handled the same way everywhere.
The reason is reconnaissance. Error output can expose framework names and versions, file paths and SQL errors, which help an attacker find injection points and known weaknesses.
What to look for in a diff
| Pattern | Why it matters |
|---|---|
| Returning the exception message in the response body | Leaks internals |
| Debug mode flags enabled in a shared config | Detailed pages in production |
| A try block that swallows errors silently | Failures go unnoticed |
| Different messages for unknown user and wrong password | Reveals which accounts exist |
| New endpoint with its own error format | Bypasses the global handler |
Status codes carry signal
The cheat sheet advises 4xx for errors caused by the client and 5xx for server failures the application cannot fulfill, and suggests monitoring 5xx rates because they can signal problems with certain inputs. A reviewer can use that: if a change turns validation failures into 500 responses, you lose a clean signal and may hide a crash that someone can trigger on purpose.
Steps for a review
- Find every place the diff builds a response from an exception. Check what text is included.
- Check that the full error, with identifiers to correlate, is logged server side.
- Look for a global handler. If the framework provides one, confirm the new code does not bypass it.
- Compare messages for related failures, such as login failures, so they do not leak account existence.
- Ask for a test that triggers an error and asserts the response has no stack trace or path.
// risky
res.status(500).send(err.stack);
// safer
logger.error({ err, requestId });
res.status(500).json({ message: "Something went wrong", requestId });
Returning a request ID lets support find the log entry without exposing anything.
What the source does not say
The cheat sheet does not describe a fail closed rule. That is a common design principle for security checks, and worth applying in authorization code, but treat it as team guidance and not as something this page requires.
Where Safeguard fits
Safeguard scans dependencies and builds SBOMs, so framework versions with known error handling issues show up in your inventory. Try the free scan at gold.safeguard.sh/scan.
Quick check
Why not show users the real error?
Detailed errors expose framework versions, paths and SQL errors that help attackers. Log them server side instead.
Why watch 5xx rates?
OWASP notes they can signal problems with certain inputs, including crafted ones.
Sources
Last reviewed: 19 October 2026.