Merge branch 'master' into node-4101-slack-trigger-add-reaction-emoji-filtering-to-prevent

This commit is contained in:
Jon
2026-04-17 19:02:54 +01:00
committed by GitHub
4 changed files with 42 additions and 6 deletions

View File

@@ -113,6 +113,36 @@ describe('CredentialsOverwrites', () => {
expect(result).toEqual(data);
});
it('should not crash when skipTypes is undefined', () => {
// Simulate version mismatch where skipTypes is not present on the config object
globalConfig.credentials.overwrite.skipTypes =
undefined as unknown as CommaSeparatedStringArray<string>;
const result = credentialsOverwrites.applyOverwrite('test', {
username: '',
password: '',
});
expect(result).toEqual({ username: 'user', password: 'pass' });
});
it('should not crash when overwrite config object is undefined', () => {
// Simulate a DI/version mismatch where the nested overwrite config is undefined
const savedOverwrite = globalConfig.credentials.overwrite;
globalConfig.credentials.overwrite = undefined as never;
try {
const result = credentialsOverwrites.applyOverwrite('test', {
username: '',
password: '',
});
expect(result).toEqual({ username: 'user', password: 'pass' });
} finally {
globalConfig.credentials.overwrite = savedOverwrite;
}
});
describe('N8N_SKIP_CREDENTIAL_OVERWRITE', () => {
beforeEach(() => {
globalConfig.credentials.overwrite.skipTypes = [

View File

@@ -147,7 +147,7 @@ export class CredentialsOverwrites {
// customized (any overwrite field has a non-empty value that differs from
// the overwrite value). Since overwrites are never persisted to the DB,
// any non-empty stored value that differs from the overwrite is user-set.
if (this.globalConfig.credentials.overwrite.skipTypes.includes(type)) {
if (this.globalConfig.credentials.overwrite?.skipTypes?.includes(type)) {
const isFieldCustomized = (key: string) => {
const storedValue = data[key];
return (
@@ -208,11 +208,17 @@ export class CredentialsOverwrites {
private get(name: string): ICredentialDataDecryptedObject | undefined {
const parentTypes = this.credentialTypes.getParentTypes(name);
return [name, ...parentTypes]
const entries = [name, ...parentTypes]
.reverse()
.map((type) => this.overwriteData[type])
.filter((type) => !!type)
.reduce((acc, current) => Object.assign(acc, current), {});
.filter((type): type is ICredentialDataDecryptedObject => !!type);
if (entries.length === 0) return undefined;
return entries.reduce(
(acc, current) => Object.assign(acc, current),
{} as ICredentialDataDecryptedObject,
);
}
getAll(): ICredentialsOverwrite {

View File

@@ -52,7 +52,7 @@ describe('getHtmlSandboxCSP', () => {
it('should return correct CSP sandbox directive', () => {
const csp = getHtmlSandboxCSP();
expect(csp).toBe(
'sandbox allow-downloads allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-presentation allow-scripts allow-top-navigation-by-user-activation allow-top-navigation-to-custom-protocols',
'sandbox allow-downloads allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-scripts allow-top-navigation-by-user-activation allow-top-navigation-to-custom-protocols',
);
});

View File

@@ -13,5 +13,5 @@ export const isFormHtmlSandboxingDisabled = () => {
* Returns the CSP header value that sandboxes the HTML page into a separate origin.
*/
export const getHtmlSandboxCSP = (): string => {
return 'sandbox allow-downloads allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-presentation allow-scripts allow-top-navigation-by-user-activation allow-top-navigation-to-custom-protocols';
return 'sandbox allow-downloads allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-scripts allow-top-navigation-by-user-activation allow-top-navigation-to-custom-protocols';
};