fix(core): Validate credential data before encryption (#12885)

This commit is contained in:
Tomi Turtiainen 2025-01-29 09:10:04 +02:00 committed by GitHub
parent f32eef85bd
commit 3d27a14987
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 18 additions and 1 deletions

View file

@ -1,6 +1,7 @@
import { Container } from '@n8n/di'; import { Container } from '@n8n/di';
import { mock } from 'jest-mock-extended'; import { mock } from 'jest-mock-extended';
import type { CredentialInformation } from 'n8n-workflow'; import type { CredentialInformation } from 'n8n-workflow';
import { AssertionError } from 'node:assert';
import { CREDENTIAL_ERRORS } from '@/constants'; import { CREDENTIAL_ERRORS } from '@/constants';
import { Cipher } from '@/encryption/cipher'; import { Cipher } from '@/encryption/cipher';
@ -106,4 +107,15 @@ describe('Credentials', () => {
expect(decryptedData.password).toBe('testpass'); expect(decryptedData.password).toBe('testpass');
}); });
}); });
describe('setData', () => {
test.each<{}>([[123], [null], [undefined]])(
'should throw an AssertionError when data is %s',
(data) => {
const credentials = new Credentials<{}>(nodeCredentials, credentialType);
expect(() => credentials.setData(data)).toThrow(AssertionError);
},
);
});
}); });

View file

@ -20,4 +20,5 @@ export const CREDENTIAL_ERRORS = {
DECRYPTION_FAILED: DECRYPTION_FAILED:
'Credentials could not be decrypted. The likely reason is that a different "encryptionKey" was used to encrypt the data.', 'Credentials could not be decrypted. The likely reason is that a different "encryptionKey" was used to encrypt the data.',
INVALID_JSON: 'Decrypted credentials data is not valid JSON.', INVALID_JSON: 'Decrypted credentials data is not valid JSON.',
INVALID_DATA: 'Credentials data is not in a valid format.',
}; };

View file

@ -1,11 +1,13 @@
import { Container } from '@n8n/di'; import { Container } from '@n8n/di';
import type { ICredentialDataDecryptedObject, ICredentialsEncrypted } from 'n8n-workflow'; import type { ICredentialDataDecryptedObject, ICredentialsEncrypted } from 'n8n-workflow';
import { ApplicationError, ICredentials, jsonParse } from 'n8n-workflow'; import { ApplicationError, ICredentials, jsonParse } from 'n8n-workflow';
import * as a from 'node:assert';
import { CREDENTIAL_ERRORS } from '@/constants'; import { CREDENTIAL_ERRORS } from '@/constants';
import { Cipher } from '@/encryption/cipher'; import { Cipher } from '@/encryption/cipher';
import { isObjectLiteral } from '@/utils';
class CredentialDataError extends ApplicationError { export class CredentialDataError extends ApplicationError {
constructor({ name, type, id }: Credentials<object>, message: string, cause?: unknown) { constructor({ name, type, id }: Credentials<object>, message: string, cause?: unknown) {
super(message, { super(message, {
extra: { name, type, id }, extra: { name, type, id },
@ -23,6 +25,8 @@ export class Credentials<
* Sets new credential object * Sets new credential object
*/ */
setData(data: T): void { setData(data: T): void {
a.ok(isObjectLiteral(data));
this.data = this.cipher.encrypt(data); this.data = this.cipher.encrypt(data);
} }