11import { badRequest , HttpError } from "../utils/httpError.js" ;
22import { env } from "../config/env.js" ;
33
4+ const sensitiveKeyPattern = / ( a u t h o r i z a t i o n | c o o k i e | t o k e n | s e s s i o n | s e c r e t | p a s s w o r d | a p i [ - _ ] ? k e y | j w t ) / i;
5+
6+ function sanitizeString ( value ) {
7+ let out = String ( value || "" ) ;
8+ out = out . replace ( / B e a r e r \s + [ A - Z a - z 0 - 9 \- . _ ~ + / ] + = * / gi, "Bearer [REDACTED]" ) ;
9+ out = out . replace ( / X B L 3 \. 0 \s + x = [ ^ ; ] + ; [ ^ \s ] + / gi, "XBL3.0 x=[REDACTED];[REDACTED]" ) ;
10+ out = out . replace ( / ( s e s s i o n t i c k e t | e n t i t y t o k e n | t o k e n | p a s s w o r d | s e c r e t | a p i [ _ - ] ? k e y ) = ( [ ^ & \s ] + ) / gi, "$1=[REDACTED]" ) ;
11+ return out ;
12+ }
13+
14+ function sanitizeValue ( value , depth = 0 ) {
15+ if ( value === null || value === undefined ) return value ;
16+ if ( depth > 6 ) return "[TRUNCATED]" ;
17+
18+ const t = typeof value ;
19+ if ( t === "string" ) return sanitizeString ( value ) ;
20+ if ( t === "number" || t === "boolean" ) return value ;
21+ if ( Array . isArray ( value ) ) return value . map ( v => sanitizeValue ( v , depth + 1 ) ) ;
22+ if ( t !== "object" ) return sanitizeString ( value ) ;
23+
24+ const out = { } ;
25+ for ( const [ key , v ] of Object . entries ( value ) ) {
26+ if ( sensitiveKeyPattern . test ( key ) ) {
27+ out [ key ] = "[REDACTED]" ;
28+ } else {
29+ out [ key ] = sanitizeValue ( v , depth + 1 ) ;
30+ }
31+ }
32+ return out ;
33+ }
34+
435export function notFoundHandler ( req , res , next ) {
536 next ( new HttpError ( 404 , `Route ${ req . method } ${ req . originalUrl } not found` , undefined , "HTTP_404" ) ) ;
637}
@@ -11,17 +42,20 @@ export function errorHandler(err, req, res, next) {
1142 }
1243
1344 const status = err instanceof HttpError ? err . status : 500 ;
14- const code = err . code || ( err instanceof HttpError ? `HTTP_${ status } ` : "INTERNAL" ) ;
45+ const code = err instanceof HttpError ? ( err . code || `HTTP_${ status } ` ) : "INTERNAL" ;
46+ const safeMessage = status >= 500 ? "Internal Server Error" : sanitizeString ( err . message || "Error" ) ;
47+ const safeDetails = sanitizeValue ( err . details ) ;
48+ const safeStack = err . stack ? sanitizeString ( err . stack ) : undefined ;
1549
1650 const logPayload = {
1751 requestId : req . id ,
1852 method : req . method ,
1953 url : req . originalUrl ,
2054 status,
2155 code,
22- message : err . message ,
23- details : err . details ,
24- stack : err . stack
56+ message : sanitizeString ( err . message || safeMessage ) ,
57+ details : safeDetails ,
58+ stack : safeStack
2559 } ;
2660
2761 try {
@@ -32,13 +66,14 @@ export function errorHandler(err, req, res, next) {
3266
3367 const body = {
3468 error : {
35- code, message : err . message || "Internal Server Error"
69+ code,
70+ message : safeMessage
3671 }
3772 } ;
3873
3974 if ( env . NODE_ENV !== "production" ) {
40- if ( err . details ) body . error . details = err . details ;
41- if ( err . stack ) body . error . stack = err . stack ;
75+ if ( safeDetails !== undefined ) body . error . details = safeDetails ;
76+ if ( safeStack ) body . error . stack = safeStack ;
4277 }
4378
4479 res . status ( status ) . json ( body ) ;
0 commit comments