From df24dd9417959067601eac682ce4b37ce72677d2 Mon Sep 17 00:00:00 2001 From: Tomi Turtiainen <10324676+tomi@users.noreply.github.com> Date: Thu, 9 Jan 2025 10:36:42 +0200 Subject: [PATCH] fix(core): Disallow code generation in task runner --- docker/images/n8n/n8n-task-runners.json | 5 ++++- .../__tests__/js-task-runner.test.ts | 1 + .../src/js-task-runner/js-task-runner.ts | 14 +++++--------- .../cli/src/task-runners/task-runner-process.ts | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docker/images/n8n/n8n-task-runners.json b/docker/images/n8n/n8n-task-runners.json index c64d0ecdd04a5..1f38cf6d930ba 100644 --- a/docker/images/n8n/n8n-task-runners.json +++ b/docker/images/n8n/n8n-task-runners.json @@ -4,7 +4,10 @@ "runner-type": "javascript", "workdir": "/home/node", "command": "/usr/local/bin/node", - "args": ["/usr/local/lib/node_modules/n8n/node_modules/@n8n/task-runner/dist/start.js"], + "args": [ + "--disallow-code-generation-from-strings", + "/usr/local/lib/node_modules/n8n/node_modules/@n8n/task-runner/dist/start.js" + ], "allowed-env": [ "PATH", "GENERIC_TIMEZONE", 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 5ebd965e874f4..9c5fc957baeb1 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 @@ -302,6 +302,7 @@ describe('JsTaskRunner', () => { ['typeof clearInterval', 'function'], ['typeof clearImmediate', 'function'], ], + eval: [['eval("1+2")', 3]], 'JS built-ins': [ ['typeof btoa', 'function'], ['typeof atob', 'function'], diff --git a/packages/@n8n/task-runner/src/js-task-runner/js-task-runner.ts b/packages/@n8n/task-runner/src/js-task-runner/js-task-runner.ts index ab2cc3a30428e..5ff65fbc12204 100644 --- a/packages/@n8n/task-runner/src/js-task-runner/js-task-runner.ts +++ b/packages/@n8n/task-runner/src/js-task-runner/js-task-runner.ts @@ -19,7 +19,7 @@ import type { } from 'n8n-workflow'; import * as a from 'node:assert'; import { inspect } from 'node:util'; -import { runInNewContext, type Context } from 'node:vm'; +import { type Context, createContext, runInContext } from 'node:vm'; import type { MainConfig } from '@/config/main-config'; import { UnsupportedFunctionError } from '@/js-task-runner/errors/unsupported-function.error'; @@ -160,8 +160,6 @@ export class JsTaskRunner extends TaskRunner { return { // Exposed Node.js globals in vm2 Buffer, - Function, - eval, setTimeout, setInterval, setImmediate, @@ -205,7 +203,7 @@ export class JsTaskRunner extends TaskRunner { signal.addEventListener('abort', abortHandler, { once: true }); - const taskResult = runInNewContext( + const taskResult = runInContext( `globalThis.global = globalThis; module.exports = async function VmCodeWrapper() {${settings.code}\n}()`, context, { timeout: this.taskTimeout * 1000 }, @@ -268,7 +266,7 @@ export class JsTaskRunner extends TaskRunner { signal.addEventListener('abort', abortHandler); - const taskResult = runInNewContext( + const taskResult = runInContext( `module.exports = async function VmCodeWrapper() {${settings.code}\n}()`, context, { timeout: this.taskTimeout * 1000 }, @@ -470,7 +468,7 @@ export class JsTaskRunner extends TaskRunner { dataProxy: IWorkflowDataProxyData, additionalProperties: Record = {}, ): Context { - const context: Context = { + return createContext({ [inspect.custom]: () => '[[ExecutionContext]]', require: this.requireResolver, module: {}, @@ -480,8 +478,6 @@ export class JsTaskRunner extends TaskRunner { ...dataProxy, ...this.buildRpcCallObject(taskId), ...additionalProperties, - }; - - return context; + }); } } diff --git a/packages/cli/src/task-runners/task-runner-process.ts b/packages/cli/src/task-runners/task-runner-process.ts index 5129ae98b110d..7e83e56ca0dc9 100644 --- a/packages/cli/src/task-runners/task-runner-process.ts +++ b/packages/cli/src/task-runners/task-runner-process.ts @@ -106,7 +106,7 @@ export class TaskRunnerProcess extends TypedEmitter { startNode(grantToken: string, taskBrokerUri: string) { const startScript = require.resolve('@n8n/task-runner/start'); - return spawn('node', [startScript], { + return spawn('node', ['--disallow-code-generation-from-strings', startScript], { env: this.getProcessEnvVars(grantToken, taskBrokerUri), }); }