diff --git a/.changeset/brave-apples-move.md b/.changeset/brave-apples-move.md new file mode 100644 index 0000000000..7a1fa86a56 --- /dev/null +++ b/.changeset/brave-apples-move.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': patch +--- + +Fixed a potential crash when passing an object with a `null` prototype as log meta. diff --git a/packages/backend-app-api/src/logging/WinstonLogger.test.ts b/packages/backend-app-api/src/logging/WinstonLogger.test.ts index d025719d9a..06f9cdd4c3 100644 --- a/packages/backend-app-api/src/logging/WinstonLogger.test.ts +++ b/packages/backend-app-api/src/logging/WinstonLogger.test.ts @@ -65,6 +65,10 @@ describe('WinstonLogger', () => { level: 'error', message: { nested: 'hello (world) from nested object', + null: null, + nullProto: Object.create(null, { + foo: { value: 'hello foo', enumerable: true }, + }), }, }; @@ -74,6 +78,10 @@ describe('WinstonLogger', () => { ...log, message: { nested: '[REDACTED] (world) from nested object', + null: null, + nullProto: { + foo: 'hello foo', // read only prop is not redacted + }, }, }), ); diff --git a/packages/backend-app-api/src/logging/WinstonLogger.ts b/packages/backend-app-api/src/logging/WinstonLogger.ts index 8d4b37bb8d..3fcb4142b6 100644 --- a/packages/backend-app-api/src/logging/WinstonLogger.ts +++ b/packages/backend-app-api/src/logging/WinstonLogger.ts @@ -87,11 +87,15 @@ export class WinstonLogger implements RootLoggerService { const replace = (obj: TransformableInfo) => { for (const key in obj) { - if (obj.hasOwnProperty(key)) { + if (Object.hasOwn(obj, key)) { if (typeof obj[key] === 'object') { obj[key] = replace(obj[key] as TransformableInfo); } else if (typeof obj[key] === 'string') { - obj[key] = obj[key]?.replace(redactionPattern, '[REDACTED]'); + try { + obj[key] = obj[key]?.replace(redactionPattern, '[REDACTED]'); + } catch { + /* ignore read only properties */ + } } } }