Skip to content

Commit a33ff6f

Browse files
feat: Enhance Error Redaction (#609)
* feat: Enhance Error Redaction * docs: DLP remarks * chore(deps): Pin `karma-webpack`
1 parent fc7268b commit a33ff6f

4 files changed

Lines changed: 46 additions & 4 deletions

File tree

core/packages/gaxios/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,12 @@ over other authentication methods, i.e., application default credentials.
160160
*
161161
* Set `false` to disable.
162162
*
163+
* @remarks
164+
*
165+
* This does not replace the requirement for an active Data Loss Prevention (DLP) provider. For DLP suggestions, see:
166+
* - https://cloud.google.com/sensitive-data-protection/docs/redacting-sensitive-data#dlp_deidentify_replace_infotype-nodejs
167+
* - https://cloud.google.com/sensitive-data-protection/docs/infotypes-reference#credentials_and_secrets
168+
*
163169
* @experimental
164170
*/
165171
errorRedactor?: typeof defaultErrorRedactor | false;

core/packages/gaxios/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
"karma-mocha": "^2.0.0",
6969
"karma-remap-coverage": "^0.1.5",
7070
"karma-sourcemap-loader": "^0.4.0",
71-
"karma-webpack": "^5.0.0",
71+
"karma-webpack": "5.0.0",
7272
"linkinator": "^4.0.0",
7373
"mocha": "^8.0.0",
7474
"multiparty": "^4.2.1",

core/packages/gaxios/src/common.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,12 @@ export interface GaxiosOptions {
209209
/**
210210
* An experimental error redactor.
211211
*
212+
* @remarks
213+
*
214+
* This does not replace the requirement for an active Data Loss Prevention (DLP) provider. For DLP suggestions, see:
215+
* - https://cloud.google.com/sensitive-data-protection/docs/redacting-sensitive-data#dlp_deidentify_replace_infotype-nodejs
216+
* - https://cloud.google.com/sensitive-data-protection/docs/infotypes-reference#credentials_and_secrets
217+
*
212218
* @experimental
213219
*/
214220
errorRedactor?: typeof defaultErrorRedactor | false;
@@ -359,6 +365,16 @@ export function defaultErrorRedactor<T = any>(data: {
359365
if (/^authentication$/.test(key)) {
360366
headers[key] = REDACT;
361367
}
368+
369+
// any casing of `Authorization`
370+
if (/^authorization$/.test(key)) {
371+
headers[key] = REDACT;
372+
}
373+
374+
// anything containing secret, such as 'client secret'
375+
if (/secret/.test(key)) {
376+
headers[key] = REDACT;
377+
}
362378
}
363379
}
364380

@@ -370,7 +386,11 @@ export function defaultErrorRedactor<T = any>(data: {
370386
) {
371387
const text = obj[key];
372388

373-
if (/grant_type=/.test(text) || /assertion=/.test(text)) {
389+
if (
390+
/grant_type=/.test(text) ||
391+
/assertion=/.test(text) ||
392+
/secret/.test(text)
393+
) {
374394
obj[key] = REDACT;
375395
}
376396
}
@@ -385,6 +405,10 @@ export function defaultErrorRedactor<T = any>(data: {
385405
if ('assertion' in obj) {
386406
obj['assertion'] = REDACT;
387407
}
408+
409+
if ('client_secret' in obj) {
410+
obj['client_secret'] = REDACT;
411+
}
388412
}
389413
}
390414

@@ -404,6 +428,10 @@ export function defaultErrorRedactor<T = any>(data: {
404428
url.searchParams.set('token', REDACT);
405429
}
406430

431+
if (url.searchParams.has('client_secret')) {
432+
url.searchParams.set('client_secret', REDACT);
433+
}
434+
407435
data.config.url = url.toString();
408436
} catch {
409437
// ignore error - no need to parse an invalid URL

core/packages/gaxios/test/test.getch.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -704,20 +704,23 @@ describe('🎏 data handling', () => {
704704

705705
const customURL = new URL(url);
706706
customURL.searchParams.append('token', 'sensitive');
707+
customURL.searchParams.append('client_secret', 'data');
707708
customURL.searchParams.append('random', 'non-sensitive');
708709

709710
const config: GaxiosOptions = {
710711
headers: {
711712
authentication: 'My Auth',
713+
authorization: 'My Auth',
712714
'content-type': 'application/x-www-form-urlencoded',
713715
random: 'data',
714716
},
715717
data: {
716718
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
717719
assertion: 'somesensitivedata',
718720
unrelated: 'data',
721+
client_secret: 'data',
719722
},
720-
body: 'grant_type=somesensitivedata&assertion=somesensitivedata',
723+
body: 'grant_type=somesensitivedata&assertion=somesensitivedata&client_secret=data',
721724
};
722725

723726
// simulate JSON response
@@ -756,13 +759,15 @@ describe('🎏 data handling', () => {
756759
assert.deepStrictEqual(e.config.headers, {
757760
...config.headers, // non-redactables should be present
758761
authentication: REDACT,
762+
authorization: REDACT,
759763
});
760764

761765
// config redactions - data
762766
assert.deepStrictEqual(e.config.data, {
763767
...config.data, // non-redactables should be present
764768
grant_type: REDACT,
765769
assertion: REDACT,
770+
client_secret: REDACT,
766771
});
767772

768773
// config redactions - body
@@ -773,6 +778,7 @@ describe('🎏 data handling', () => {
773778
const resultURL = new URL(e.config.url);
774779
assert.notDeepStrictEqual(resultURL.toString(), customURL.toString());
775780
customURL.searchParams.set('token', REDACT);
781+
customURL.searchParams.set('client_secret', REDACT);
776782
assert.deepStrictEqual(resultURL.toString(), customURL.toString());
777783

778784
// response redactions
@@ -781,11 +787,13 @@ describe('🎏 data handling', () => {
781787
assert.deepStrictEqual(e.response.headers, {
782788
...responseHeaders, // non-redactables should be present
783789
authentication: REDACT,
790+
authorization: REDACT,
784791
});
785792
assert.deepStrictEqual(e.response.data, {
786793
...response, // non-redactables should be present
787-
grant_type: REDACT,
788794
assertion: REDACT,
795+
client_secret: REDACT,
796+
grant_type: REDACT,
789797
});
790798
} finally {
791799
scope.done();

0 commit comments

Comments
 (0)