This document defines the safe error message policy enforced by the TalentTrust backend. The goal is to prevent information disclosure through API error responses (CWE-209, OWASP A01:2021).
- Never expose internals. Stack traces, file paths, SQL fragments, dependency paths, and raw syscall error codes are never included in API responses, regardless of
NODE_ENV. - Stable machine codes. Every error response includes a machine-readable
codefield that clients can rely on for programmatic handling. These codes do not change between releases without a migration notice. - Safe human-readable messages. The
messagefield contains a helpful but non-revealing description. If an error message is detected to contain unsafe content, it is replaced by the canonical fallback for its code. - Consistent envelope. All error responses use the same JSON shape:
{ "error": { "code": "machine_readable_code", "message": "safe human-readable message", "requestId": "correlation-id" } }
| Code | HTTP Status | Canonical Message |
|---|---|---|
internal_error |
500 | An unexpected error occurred |
invalid_json |
400 | Malformed JSON payload |
validation_error |
400 | Request validation failed |
not_found |
404 | The requested resource was not found |
unauthorized |
401 | Authentication is required |
forbidden |
403 | You do not have permission to perform this action |
dependency_unavailable |
503 | A required service is temporarily unavailable |
rate_limited |
429 | Too many requests — please try again later |
conflict |
409 | The request conflicts with the current state |
bad_request |
400 | The request could not be processed |
The policy is implemented in src/errors/safeErrors.ts and enforced by:
mapErrorToPayload()insrc/errors/appError.ts— the canonical error serializer used by the envelope error handler.errorHandler()insrc/middleware/errorHandlers.ts— the global Express error handler mounted inapp.ts.errorHandler()insrc/middleware/errorHandler.ts— the alternative handler used by some route modules.errorHandler()insrc/middleware/error.middleware.ts— the legacy handler retained for backward compatibility.
sanitizeErrorMessage(message, code) checks the message against a list of forbidden patterns. If any match is found, the canonical fallback for the error code is returned instead.
Forbidden patterns include:
- V8 stack frames (
at Module._compile (...)) - Absolute file paths (
/src/app.ts:12) node_modules/references- Raw syscall errors (
ECONNREFUSED,ENOTFOUND,ETIMEDOUT) - SQL fragments (
SELECT,INSERT, etc.) - Credential-related field names (
password,secret,token,apikey)
The policy is enforced by:
- Unit tests (
src/errors/safeErrors.test.ts) — verify thatcontainsUnsafeContent,safeMessageForCode, andsanitizeErrorMessagebehave correctly for all known safe and unsafe patterns. - Integration tests (
src/errors/errorMessagePolicy.integration.test.ts) — fire HTTP requests at the running application and assert that no response body contains forbidden patterns, and that the envelope shape and machine codes are stable. - Existing handler tests — updated to assert that stack traces are never present and that 500 responses always use safe generic messages.
- Server-side logging (
console.error) still receives the full error including stack traces for debugging purposes. - The
exposeflag onAppErrorcontrols whether the developer-provided message is used (after sanitization) or replaced entirely with the canonical fallback. - Validation errors intentionally include field-level detail (e.g., "name is required") since these are user-facing input guidance, not internal implementation leakage.