mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-22 20:29:08 +00:00
fix(core): Validate customData keys and values (#5920) (no-changelog)
* fix(core): Validate customData keys and values Throws errors in manual mode and ignores and logs values in production * fix: validate customData key characters * refactor: review changes * fix: logger not initialised for metadata tests * fix: allow numbers for values
This commit is contained in:
@@ -1653,10 +1653,24 @@ export function getAdditionalKeys(
|
||||
customData: runExecutionData
|
||||
? {
|
||||
set(key: string, value: string): void {
|
||||
setWorkflowExecutionMetadata(runExecutionData, key, value);
|
||||
try {
|
||||
setWorkflowExecutionMetadata(runExecutionData, key, value);
|
||||
} catch (e) {
|
||||
if (mode === 'manual') {
|
||||
throw e;
|
||||
}
|
||||
Logger.verbose(e.message);
|
||||
}
|
||||
},
|
||||
setAll(obj: Record<string, string>): void {
|
||||
setAllWorkflowExecutionMetadata(runExecutionData, obj);
|
||||
try {
|
||||
setAllWorkflowExecutionMetadata(runExecutionData, obj);
|
||||
} catch (e) {
|
||||
if (mode === 'manual') {
|
||||
throw e;
|
||||
}
|
||||
Logger.verbose(e.message);
|
||||
}
|
||||
},
|
||||
get(key: string): string {
|
||||
return getWorkflowExecutionMetadata(runExecutionData, key);
|
||||
|
||||
@@ -1,7 +1,20 @@
|
||||
import type { IRunExecutionData } from 'n8n-workflow';
|
||||
import { LoggerProxy as Logger } from 'n8n-workflow';
|
||||
|
||||
export const KV_LIMIT = 10;
|
||||
|
||||
export class ExecutionMetadataValidationError extends Error {
|
||||
constructor(
|
||||
public type: 'key' | 'value',
|
||||
key: unknown,
|
||||
message?: string,
|
||||
options?: ErrorOptions,
|
||||
) {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
super(message ?? `Custom data ${type}s must be a string (key "${key}")`, options);
|
||||
}
|
||||
}
|
||||
|
||||
export function setWorkflowExecutionMetadata(
|
||||
executionData: IRunExecutionData,
|
||||
key: string,
|
||||
@@ -17,16 +30,44 @@ export function setWorkflowExecutionMetadata(
|
||||
) {
|
||||
return;
|
||||
}
|
||||
executionData.resultData.metadata[String(key).slice(0, 50)] = String(value).slice(0, 255);
|
||||
if (typeof key !== 'string') {
|
||||
throw new ExecutionMetadataValidationError('key', key);
|
||||
}
|
||||
if (key.replace(/[A-Za-z0-9_]/g, '').length !== 0) {
|
||||
throw new ExecutionMetadataValidationError(
|
||||
'key',
|
||||
key,
|
||||
`Custom date key can only contain characters "A-Za-z0-9_" (key "${key}")`,
|
||||
);
|
||||
}
|
||||
if (typeof value !== 'string' && typeof value !== 'number' && typeof value !== 'bigint') {
|
||||
throw new ExecutionMetadataValidationError('value', key);
|
||||
}
|
||||
const val = String(value);
|
||||
if (key.length > 50) {
|
||||
Logger.error('Custom data key over 50 characters long. Truncating to 50 characters.');
|
||||
}
|
||||
if (val.length > 255) {
|
||||
Logger.error('Custom data value over 255 characters long. Truncating to 255 characters.');
|
||||
}
|
||||
executionData.resultData.metadata[key.slice(0, 50)] = val.slice(0, 255);
|
||||
}
|
||||
|
||||
export function setAllWorkflowExecutionMetadata(
|
||||
executionData: IRunExecutionData,
|
||||
obj: Record<string, string>,
|
||||
) {
|
||||
Object.entries(obj).forEach(([key, value]) =>
|
||||
setWorkflowExecutionMetadata(executionData, key, value),
|
||||
);
|
||||
const errors: Error[] = [];
|
||||
Object.entries(obj).forEach(([key, value]) => {
|
||||
try {
|
||||
setWorkflowExecutionMetadata(executionData, key, value);
|
||||
} catch (e) {
|
||||
errors.push(e as Error);
|
||||
}
|
||||
});
|
||||
if (errors.length) {
|
||||
throw errors[0];
|
||||
}
|
||||
}
|
||||
|
||||
export function getAllWorkflowExecutionMetadata(
|
||||
|
||||
Reference in New Issue
Block a user