diff --git a/packages/backend-app-api/src/logging/WinstonLogger.test.ts b/packages/backend-app-api/src/logging/WinstonLogger.test.ts index 06f9cdd4c3..8f60e8dae2 100644 --- a/packages/backend-app-api/src/logging/WinstonLogger.test.ts +++ b/packages/backend-app-api/src/logging/WinstonLogger.test.ts @@ -80,7 +80,7 @@ describe('WinstonLogger', () => { nested: '[REDACTED] (world) from nested object', null: null, nullProto: { - foo: 'hello foo', // read only prop is not redacted + foo: '[REDACTED] foo', }, }, }), diff --git a/packages/backend-app-api/src/logging/WinstonLogger.ts b/packages/backend-app-api/src/logging/WinstonLogger.ts index 3fcb4142b6..cb9d81cdf1 100644 --- a/packages/backend-app-api/src/logging/WinstonLogger.ts +++ b/packages/backend-app-api/src/logging/WinstonLogger.ts @@ -86,19 +86,17 @@ export class WinstonLogger implements RootLoggerService { let redactionPattern: RegExp | undefined = undefined; const replace = (obj: TransformableInfo) => { - for (const key in obj) { - if (Object.hasOwn(obj, key)) { - if (typeof obj[key] === 'object') { - obj[key] = replace(obj[key] as TransformableInfo); - } else if (typeof obj[key] === 'string') { - try { - obj[key] = obj[key]?.replace(redactionPattern, '[REDACTED]'); - } catch { - /* ignore read only properties */ - } - } + const stringifiedFields = JSON.stringify(obj, null); + const redacted = JSON.parse( + stringifiedFields.replace(redactionPattern!, '[REDACTED]'), + ); + + for (const key in redacted) { + if (obj && Object.hasOwn(obj, key)) { + obj[key] = redacted[key]; } } + return obj; }; return {