fix: Invalid secret expression value for AWS secret keys containing / (#20433)

This commit is contained in:
Stephen Wright 2025-10-07 09:49:42 +01:00 committed by GitHub
parent ad11e77b42
commit f46b5e1640
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 50 additions and 6 deletions

View File

@ -1151,8 +1151,9 @@ export const secretOptions = (base: string) => {
if (typeof resolved !== 'object') {
return [];
}
return Object.entries(resolved).map(([secret, value]) =>
createCompletionOption({
return Object.entries(resolved).map(([secret, value]) => {
const needsBracketAccess = /\//.test(secret);
const option = createCompletionOption({
name: secret,
doc: {
name: secret,
@ -1160,8 +1161,15 @@ export const secretOptions = (base: string) => {
description: i18n.baseText('codeNodeEditor.completer.$secrets.provider.varName'),
docURL: i18n.baseText('settings.externalSecrets.docs'),
},
}),
);
});
// Override the apply handler for keys that need bracket access
if (needsBracketAccess) {
option.apply = applyBracketAccessCompletion;
}
return option;
});
} catch {
return [];
}

View File

@ -6,7 +6,12 @@ import { EditorState } from '@codemirror/state';
import { EditorView } from '@codemirror/view';
import { NodeConnectionTypes, type IConnections } from 'n8n-workflow';
import type { MockInstance } from 'vitest';
import { autocompletableNodeNames, expressionWithFirstItem, stripExcessParens } from './utils';
import {
autocompletableNodeNames,
expressionWithFirstItem,
stripExcessParens,
isAllowedInDotNotation,
} from './utils';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { mockedStore } from '@/__tests__/utils';
import { createTestingPinia } from '@pinia/testing';
@ -183,4 +188,35 @@ describe('completion utils', () => {
expect(view.state.doc.toString()).toEqual(expected);
});
});
describe('isAllowedInDotNotation', () => {
it('should return false for keys with forward slashes', () => {
expect(
isAllowedInDotNotation(
'applications/n8n/available-to-users/google-cloud-geocoding-api-key',
),
).toBe(false);
expect(isAllowedInDotNotation('path/to/secret')).toBe(false);
expect(isAllowedInDotNotation('secret/with/slashes')).toBe(false);
});
it('should return false for keys with other special characters', () => {
expect(isAllowedInDotNotation('key with spaces')).toBe(false);
expect(isAllowedInDotNotation('key-with-hyphens')).toBe(false);
expect(isAllowedInDotNotation('key.with.dots')).toBe(false);
expect(isAllowedInDotNotation('key[with]brackets')).toBe(false);
});
it('should return true for valid JavaScript identifiers', () => {
expect(isAllowedInDotNotation('validKey')).toBe(true);
expect(isAllowedInDotNotation('valid_key')).toBe(true);
expect(isAllowedInDotNotation('validKey123')).toBe(true);
expect(isAllowedInDotNotation('_validKey')).toBe(true);
});
it('should return false for keys starting with numbers', () => {
expect(isAllowedInDotNotation('123key')).toBe(false);
expect(isAllowedInDotNotation('0invalid')).toBe(false);
});
});
});

View File

@ -136,7 +136,7 @@ export const isPseudoParam = (candidate: string) => {
* Whether a string may be used as a key in object dot access notation.
*/
export const isAllowedInDotNotation = (str: string) => {
const DOT_NOTATION_BANNED_CHARS = /^(\d)|[\\ `!@#$%^&*()+\-=[\]{};':"\\|,.<>?~]/g;
const DOT_NOTATION_BANNED_CHARS = /^(\d)|[\\ `!@#$%^&*()+\-=[\]{};':"\\|,.<>?~\/]/g;
return !DOT_NOTATION_BANNED_CHARS.test(str);
};