fix(core): Fix disallowed module error in task runner (#18190)

This commit is contained in:
Iván Ovejero
2025-08-11 10:46:38 +02:00
committed by GitHub
parent b5f47ec110
commit 09caa05726
5 changed files with 22 additions and 16 deletions

View File

@@ -1008,7 +1008,7 @@ describe('JsTaskRunner', () => {
code: `return require('${module}')`, code: `return require('${module}')`,
inputItems, inputItems,
}), }),
).rejects.toThrow(`Cannot find module '${module}'`); ).rejects.toThrow(`Module '${module}' is disallowed`);
}, },
); );
@@ -1020,7 +1020,7 @@ describe('JsTaskRunner', () => {
code: `return require('${module}')`, code: `return require('${module}')`,
inputItems, inputItems,
}), }),
).rejects.toThrow(`Cannot find module '${module}'`); ).rejects.toThrow(`Module '${module}' is disallowed`);
}, },
); );
}); });
@@ -1138,7 +1138,7 @@ describe('JsTaskRunner', () => {
inputItems, inputItems,
runner, runner,
}), }),
).rejects.toThrow(`Cannot find module '${moduleName}'`); ).rejects.toThrow(`Module '${moduleName}' is disallowed`);
}, },
); );
@@ -1151,7 +1151,7 @@ describe('JsTaskRunner', () => {
inputItems, inputItems,
runner, runner,
}), }),
).rejects.toThrow(`Cannot find module '${moduleName}'`); ).rejects.toThrow(`Module '${moduleName}' is disallowed`);
}, },
); );
}); });
@@ -1200,7 +1200,7 @@ describe('JsTaskRunner', () => {
inputItems, inputItems,
runner, runner,
}), }),
).rejects.toThrow(`Cannot find module '${moduleName}'`); ).rejects.toThrow(`Module '${moduleName}' is disallowed`);
}, },
); );
@@ -1213,7 +1213,7 @@ describe('JsTaskRunner', () => {
inputItems, inputItems,
runner, runner,
}), }),
).rejects.toThrow(`Cannot find module '${moduleName}'`); ).rejects.toThrow(`Module '${moduleName}' is disallowed`);
}, },
); );
}); });

View File

@@ -1,7 +1,6 @@
import { ApplicationError } from '@n8n/errors';
import { ExecutionError } from '@/js-task-runner/errors/execution-error'; import { ExecutionError } from '@/js-task-runner/errors/execution-error';
import { DisallowedModuleError } from '../errors/disallowed-module.error';
import { createRequireResolver, type RequireResolverOpts } from '../require-resolver'; import { createRequireResolver, type RequireResolverOpts } from '../require-resolver';
describe('require resolver', () => { describe('require resolver', () => {
@@ -44,10 +43,10 @@ describe('require resolver', () => {
expect(() => resolver('lodash')).not.toThrow(); 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); const resolver = createRequireResolver(defaultOpts);
expect(() => resolver('express')).toThrow( 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', () => { describe('error handling', () => {
it('should wrap ApplicationError in ExecutionError', () => { it('should wrap DisallowedModuleError in ExecutionError', () => {
const resolver = createRequireResolver(defaultOpts); const resolver = createRequireResolver(defaultOpts);
expect(() => resolver('non-existent-module')).toThrow(ExecutionError); expect(() => resolver('non-existent-module')).toThrow(ExecutionError);
}); });
@@ -71,7 +70,7 @@ describe('require resolver', () => {
it('should include the module name in the error message', () => { it('should include the module name in the error message', () => {
const resolver = createRequireResolver(defaultOpts); const resolver = createRequireResolver(defaultOpts);
expect(() => resolver('non-existent-module')).toThrow( expect(() => resolver('non-existent-module')).toThrow(
"Cannot find module 'non-existent-module'", "Module 'non-existent-module' is disallowed",
); );
}); });
}); });

View File

@@ -0,0 +1,7 @@
import { UserError } from 'n8n-workflow';
export class DisallowedModuleError extends UserError {
constructor(moduleName: string) {
super(`Module '${moduleName}' is disallowed`);
}
}

View File

@@ -1,6 +1,6 @@
import { ApplicationError } from '@n8n/errors';
import { isBuiltin } from 'node:module'; import { isBuiltin } from 'node:module';
import { DisallowedModuleError } from './errors/disallowed-module.error';
import { ExecutionError } from './errors/execution-error'; import { ExecutionError } from './errors/execution-error';
export type RequireResolverOpts = { export type RequireResolverOpts = {
@@ -33,7 +33,7 @@ export function createRequireResolver({
: checkIsAllowed(allowedExternalModules, request); : checkIsAllowed(allowedExternalModules, request);
if (!isAllowed) { if (!isAllowed) {
const error = new ApplicationError(`Cannot find module '${request}'`); const error = new DisallowedModuleError(request);
throw new ExecutionError(error); throw new ExecutionError(error);
} }

View File

@@ -234,7 +234,7 @@ describe('JS TaskRunner execution on internal mode', () => {
expect(result).toEqual({ expect(result).toEqual({
ok: false, ok: false,
error: expect.objectContaining({ 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({ expect(result).toEqual({
ok: false, ok: false,
error: expect.objectContaining({ error: expect.objectContaining({
message: "Cannot find module 'lodash' [line 2]", message: "Module 'lodash' is disallowed [line 2]",
}), }),
}); });
}); });