Skip to content

Commit c5c6081

Browse files
authored
fix(debug): fix redaction of logger overwriting values (#79)
fix #78
1 parent f6ea72d commit c5c6081

File tree

2 files changed

+71
-6
lines changed

2 files changed

+71
-6
lines changed

__tests__/utils/debug.test.ts

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { createRedactedObject, generalRedactor } from '../../src/utils/debug';
2+
3+
describe('generalRedactor', () => {
4+
test('redacts the correct properties', () => {
5+
const context = {
6+
ACCOUNT_SID: 'ACxxxxxxx',
7+
AUTH_TOKEN: 'auth-token',
8+
SOME_URL: 'https://twilio.com/labs',
9+
};
10+
11+
const redacted = generalRedactor(context);
12+
expect(redacted.ACCOUNT_SID).toBe('ACxxxxxxx');
13+
expect(redacted.AUTH_TOKEN).toBe('[REDACTED]');
14+
expect(redacted.SOME_URL).toBe('https://twilio.com/labs');
15+
});
16+
});
17+
18+
describe('createRedactedObject', () => {
19+
test('does not modify the original object', () => {
20+
const context = {
21+
ACCOUNT_SID: 'ACxxxxxxx',
22+
AUTH_TOKEN: 'auth-token',
23+
SOME_URL: 'https://twilio.com/labs',
24+
env: {
25+
ACCOUNT_SID: 'ACyyyyyyy',
26+
AUTH_TOKEN: 'another-auth-token',
27+
},
28+
};
29+
30+
const redacted = createRedactedObject(context, generalRedactor);
31+
32+
expect(redacted).toEqual({
33+
ACCOUNT_SID: 'ACxxxxxxx',
34+
AUTH_TOKEN: '[REDACTED]',
35+
SOME_URL: 'https://twilio.com/labs',
36+
env: {
37+
ACCOUNT_SID: '[REDACTED]',
38+
AUTH_TOKEN: '[REDACTED]',
39+
},
40+
});
41+
expect(context).toEqual({
42+
ACCOUNT_SID: 'ACxxxxxxx',
43+
AUTH_TOKEN: 'auth-token',
44+
SOME_URL: 'https://twilio.com/labs',
45+
env: {
46+
ACCOUNT_SID: 'ACyyyyyyy',
47+
AUTH_TOKEN: 'another-auth-token',
48+
},
49+
});
50+
});
51+
});

src/utils/debug.ts

+20-6
Original file line numberDiff line numberDiff line change
@@ -28,38 +28,52 @@ export const generalRedactor = fastRedact({
2828
'TWILIO_API_SECRET',
2929
]),
3030
],
31-
});
31+
serialize: false,
32+
}) as <T>(x: T) => T;
3233

3334
export const allPropertiesRedactor = fastRedact({
3435
paths: ['*'],
35-
});
36+
serialize: false,
37+
}) as <T>(x: T) => T;
38+
39+
export function copyObject(obj: object) {
40+
return JSON.parse(JSON.stringify(obj));
41+
}
42+
43+
export function createRedactedObject(
44+
obj: object,
45+
redactor: typeof generalRedactor
46+
) {
47+
const copiedObject = copyObject(obj);
48+
return redactor(copiedObject);
49+
}
3650

3751
debug.formatters.P = function protectedFormatterMultiline(v: any): string {
3852
if (typeof v === 'object') {
39-
v = JSON.parse(generalRedactor(v));
53+
v = createRedactedObject(v, generalRedactor);
4054
}
4155

4256
return debug.formatters.O.bind(debug)(v);
4357
};
4458

4559
debug.formatters.p = function protectedFormatterSameline(v: any): string {
4660
if (typeof v === 'object') {
47-
v = JSON.parse(generalRedactor(v));
61+
v = createRedactedObject(v, generalRedactor);
4862
}
4963

5064
return debug.formatters.o.bind(debug)(v);
5165
};
5266

5367
debug.formatters.R = function redactedFormatterMultiline(v: any): string {
5468
if (typeof v === 'object') {
55-
v = JSON.parse(allPropertiesRedactor(v));
69+
v = createRedactedObject(v, allPropertiesRedactor);
5670
}
5771
return debug.formatters.O.bind(debug)(v);
5872
};
5973

6074
debug.formatters.r = function redactedFormatterSameline(v: any): string {
6175
if (typeof v === 'object') {
62-
v = JSON.parse(allPropertiesRedactor(v));
76+
v = createRedactedObject(v, allPropertiesRedactor);
6377
}
6478
return debug.formatters.o.bind(debug)(v);
6579
};

0 commit comments

Comments
 (0)