From 09caa0572623ff4aead2aeb708978528d9c110ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Mon, 11 Aug 2025 10:46:38 +0200 Subject: [PATCH] fix(core): Fix disallowed module error in task runner (#18190) --- .../js-task-runner/__tests__/js-task-runner.test.ts | 12 ++++++------ .../__tests__/require-resolver.test.ts | 11 +++++------ .../js-task-runner/errors/disallowed-module.error.ts | 7 +++++++ .../src/js-task-runner/require-resolver.ts | 4 ++-- .../js-task-runner-execution.integration.test.ts | 4 ++-- 5 files changed, 22 insertions(+), 16 deletions(-) create mode 100644 packages/@n8n/task-runner/src/js-task-runner/errors/disallowed-module.error.ts diff --git a/packages/@n8n/task-runner/src/js-task-runner/__tests__/js-task-runner.test.ts b/packages/@n8n/task-runner/src/js-task-runner/__tests__/js-task-runner.test.ts index 422bef3e88..970d08dab8 100644 --- a/packages/@n8n/task-runner/src/js-task-runner/__tests__/js-task-runner.test.ts +++ b/packages/@n8n/task-runner/src/js-task-runner/__tests__/js-task-runner.test.ts @@ -1008,7 +1008,7 @@ describe('JsTaskRunner', () => { code: `return require('${module}')`, inputItems, }), - ).rejects.toThrow(`Cannot find module '${module}'`); + ).rejects.toThrow(`Module '${module}' is disallowed`); }, ); @@ -1020,7 +1020,7 @@ describe('JsTaskRunner', () => { code: `return require('${module}')`, inputItems, }), - ).rejects.toThrow(`Cannot find module '${module}'`); + ).rejects.toThrow(`Module '${module}' is disallowed`); }, ); }); @@ -1138,7 +1138,7 @@ describe('JsTaskRunner', () => { inputItems, runner, }), - ).rejects.toThrow(`Cannot find module '${moduleName}'`); + ).rejects.toThrow(`Module '${moduleName}' is disallowed`); }, ); @@ -1151,7 +1151,7 @@ describe('JsTaskRunner', () => { inputItems, runner, }), - ).rejects.toThrow(`Cannot find module '${moduleName}'`); + ).rejects.toThrow(`Module '${moduleName}' is disallowed`); }, ); }); @@ -1200,7 +1200,7 @@ describe('JsTaskRunner', () => { inputItems, runner, }), - ).rejects.toThrow(`Cannot find module '${moduleName}'`); + ).rejects.toThrow(`Module '${moduleName}' is disallowed`); }, ); @@ -1213,7 +1213,7 @@ describe('JsTaskRunner', () => { inputItems, runner, }), - ).rejects.toThrow(`Cannot find module '${moduleName}'`); + ).rejects.toThrow(`Module '${moduleName}' is disallowed`); }, ); }); diff --git a/packages/@n8n/task-runner/src/js-task-runner/__tests__/require-resolver.test.ts b/packages/@n8n/task-runner/src/js-task-runner/__tests__/require-resolver.test.ts index 27f65f4e4e..36061b9cc7 100644 --- a/packages/@n8n/task-runner/src/js-task-runner/__tests__/require-resolver.test.ts +++ b/packages/@n8n/task-runner/src/js-task-runner/__tests__/require-resolver.test.ts @@ -1,7 +1,6 @@ -import { ApplicationError } from '@n8n/errors'; - import { ExecutionError } from '@/js-task-runner/errors/execution-error'; +import { DisallowedModuleError } from '../errors/disallowed-module.error'; import { createRequireResolver, type RequireResolverOpts } from '../require-resolver'; describe('require resolver', () => { @@ -44,10 +43,10 @@ describe('require resolver', () => { expect(() => resolver('lodash')).not.toThrow(); }); - it('should throw when requiring non-whitelisted external modules', () => { + it('should throw when requiring non-allowlisted external modules', () => { const resolver = createRequireResolver(defaultOpts); expect(() => resolver('express')).toThrow( - new ExecutionError(new ApplicationError("Cannot find module 'express'")), + new ExecutionError(new DisallowedModuleError('express')), ); }); @@ -63,7 +62,7 @@ describe('require resolver', () => { }); describe('error handling', () => { - it('should wrap ApplicationError in ExecutionError', () => { + it('should wrap DisallowedModuleError in ExecutionError', () => { const resolver = createRequireResolver(defaultOpts); expect(() => resolver('non-existent-module')).toThrow(ExecutionError); }); @@ -71,7 +70,7 @@ describe('require resolver', () => { it('should include the module name in the error message', () => { const resolver = createRequireResolver(defaultOpts); expect(() => resolver('non-existent-module')).toThrow( - "Cannot find module 'non-existent-module'", + "Module 'non-existent-module' is disallowed", ); }); }); diff --git a/packages/@n8n/task-runner/src/js-task-runner/errors/disallowed-module.error.ts b/packages/@n8n/task-runner/src/js-task-runner/errors/disallowed-module.error.ts new file mode 100644 index 0000000000..229db23e80 --- /dev/null +++ b/packages/@n8n/task-runner/src/js-task-runner/errors/disallowed-module.error.ts @@ -0,0 +1,7 @@ +import { UserError } from 'n8n-workflow'; + +export class DisallowedModuleError extends UserError { + constructor(moduleName: string) { + super(`Module '${moduleName}' is disallowed`); + } +} diff --git a/packages/@n8n/task-runner/src/js-task-runner/require-resolver.ts b/packages/@n8n/task-runner/src/js-task-runner/require-resolver.ts index 9da36e87a1..e1a3abab5c 100644 --- a/packages/@n8n/task-runner/src/js-task-runner/require-resolver.ts +++ b/packages/@n8n/task-runner/src/js-task-runner/require-resolver.ts @@ -1,6 +1,6 @@ -import { ApplicationError } from '@n8n/errors'; import { isBuiltin } from 'node:module'; +import { DisallowedModuleError } from './errors/disallowed-module.error'; import { ExecutionError } from './errors/execution-error'; export type RequireResolverOpts = { @@ -33,7 +33,7 @@ export function createRequireResolver({ : checkIsAllowed(allowedExternalModules, request); if (!isAllowed) { - const error = new ApplicationError(`Cannot find module '${request}'`); + const error = new DisallowedModuleError(request); throw new ExecutionError(error); } diff --git a/packages/cli/test/integration/task-runners/js-task-runner-execution.integration.test.ts b/packages/cli/test/integration/task-runners/js-task-runner-execution.integration.test.ts index d85be1a7e2..582c29e844 100644 --- a/packages/cli/test/integration/task-runners/js-task-runner-execution.integration.test.ts +++ b/packages/cli/test/integration/task-runners/js-task-runner-execution.integration.test.ts @@ -234,7 +234,7 @@ describe('JS TaskRunner execution on internal mode', () => { expect(result).toEqual({ ok: false, error: expect.objectContaining({ - message: "Cannot find module 'fs' [line 2]", + message: "Module 'fs' is disallowed [line 2]", }), }); }); @@ -262,7 +262,7 @@ describe('JS TaskRunner execution on internal mode', () => { expect(result).toEqual({ ok: false, error: expect.objectContaining({ - message: "Cannot find module 'lodash' [line 2]", + message: "Module 'lodash' is disallowed [line 2]", }), }); });