From 48f047ee2ecbfbd364151816df5fc21e09ca72a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Tue, 16 Jul 2024 18:09:56 +0200 Subject: [PATCH] fix(core): Redact `csrfSecret` when returning oauth credentials to the frontend (#10075) --- .../__tests__/credentials.service.test.ts | 70 +++++++++++++++++++ .../src/credentials/credentials.service.ts | 2 +- 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 packages/cli/src/credentials/__tests__/credentials.service.test.ts diff --git a/packages/cli/src/credentials/__tests__/credentials.service.test.ts b/packages/cli/src/credentials/__tests__/credentials.service.test.ts new file mode 100644 index 0000000000000..18216df8674ce --- /dev/null +++ b/packages/cli/src/credentials/__tests__/credentials.service.test.ts @@ -0,0 +1,70 @@ +import { CREDENTIAL_EMPTY_VALUE, type ICredentialType } from 'n8n-workflow'; +import { mock } from 'jest-mock-extended'; +import { CREDENTIAL_BLANKING_VALUE } from '@/constants'; +import type { CredentialsEntity } from '@db/entities/CredentialsEntity'; +import type { CredentialTypes } from '@/CredentialTypes'; +import { CredentialsService } from '../credentials.service'; + +describe('CredentialsService', () => { + const credType = mock({ + extends: [], + properties: [ + { + name: 'clientSecret', + type: 'string', + typeOptions: { password: true }, + doNotInherit: false, + }, + { + name: 'accessToken', + type: 'string', + typeOptions: { password: true }, + doNotInherit: false, + }, + ], + }); + const credentialTypes = mock(); + const service = new CredentialsService( + mock(), + mock(), + mock(), + mock(), + mock(), + mock(), + credentialTypes, + mock(), + mock(), + mock(), + mock(), + ); + + describe('redact', () => { + it('should redact sensitive values', () => { + const credential = mock({ + id: '123', + name: 'Test Credential', + type: 'oauth2', + }); + + const decryptedData = { + clientId: 'abc123', + clientSecret: 'sensitiveSecret', + accessToken: '', + oauthTokenData: 'super-secret', + csrfSecret: 'super-secret', + }; + + credentialTypes.getByName.calledWith(credential.type).mockReturnValue(credType); + + const redactedData = service.redact(decryptedData, credential); + + expect(redactedData).toEqual({ + clientId: 'abc123', + clientSecret: CREDENTIAL_BLANKING_VALUE, + accessToken: CREDENTIAL_EMPTY_VALUE, + oauthTokenData: CREDENTIAL_BLANKING_VALUE, + csrfSecret: CREDENTIAL_BLANKING_VALUE, + }); + }); + }); +}); diff --git a/packages/cli/src/credentials/credentials.service.ts b/packages/cli/src/credentials/credentials.service.ts index f16a2eb70d540..0ecfd31877bf2 100644 --- a/packages/cli/src/credentials/credentials.service.ts +++ b/packages/cli/src/credentials/credentials.service.ts @@ -407,7 +407,7 @@ export class CredentialsService { for (const dataKey of Object.keys(copiedData)) { // The frontend only cares that this value isn't falsy. - if (dataKey === 'oauthTokenData') { + if (dataKey === 'oauthTokenData' || dataKey === 'csrfSecret') { if (copiedData[dataKey].toString().length > 0) { copiedData[dataKey] = CREDENTIAL_BLANKING_VALUE; } else {