GitHub Advisoryadvisory · npm

GHSA-3769-jgqc-cxm7 Flowise: RCE via NodeVM Sandbox Escape in executeJavaScriptCode() nodeVMOptions Override

CRITICAL Published 2026-08-04 Modified 2026-08-04 Official page ↗
Aliases
CVE-2026-69254
Ecosystem
npm
Packages
flowise, flowise-components
Severity
Critical
CVSS vector
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H
Weaknesses
CWE-94
Reviewed
2026-08-04

Affected packages

• npm flowise: < 3.1.3 → fixed in 3.1.3 • npm flowise-components: < 3.1.3 → fixed in 3.1.3

Description

Summary A sandbox escape vulnerability in `executeJavaScriptCode()` allows any authenticated user to execute arbitrary system commands as root on the Flowise server. The function accepts caller-provided `nodeVMOptions` that override the default sandbox security settings via JavaScript's spread operator, allowing an attacker to re-enable blocked modules like `child_process` and `fs`. Details The vulnerability is in `packages/components/src/utils.ts` at line 1755: ```typescript const finalNodeVMOptions = { ...defaultNodeVMOptions, ...nodeVMOptions } The executeJavaScriptCode() function (line 1569) creates a NodeVM sandbox with secure defaults that restrict which Node.js built-in modules can be required: async (code, sandbox, options = {}) => { const { nodeVMOptions = {} } = options; // ... const defaultNodeVMOptions = { require: { builtin: builtinDeps, // restricted allowlist — blocks child_process, fs, os, etc. mock: secureWrappers }, eval: false, wasm: false } const finalNodeVMOptions = { ...defaultNodeVMOptions, ...nodeVMOptions } // ← VULN: caller overrides security settings const vm = new NodeVM(finalNodeVMOptions) } ``` The spread operator allows any caller to override require.builtin with ["*"], which permits all Node.js built-in modules including child_process. Taint 01: Route Registration `packages/server/src/routes/node-custom-functions/index.ts` (line 8) Taint 02: Controller `executeCustomFunction()` passes `req.body` to service — `packages/server/src/controllers/nodes/index.ts` (line 90) Taint 03: Service `executeCustomNodeFunction()` loads the `customFunction` node and calls `init()` with user-provided `javascriptFunction` — `packages/server/src/utils/executeCustomNodeFunction.ts` (line 49) Taint 04: Sandbox Entry Code runs inside NodeVM via `executeJavaScriptCode()` — `packages/components/src/utils.ts` (line 1760) Taint 05: Escape Inside the sandbox, the attacker requires `flowise-components/dist/src/utils.js` by absolute path (bypassing the module allowlist), obtaining a reference to `executeJavaScriptCode()` itself Taint 06: Override The attacker calls `executeJavaScriptCode()` with `nodeVMOptions: { require: { builtin: ["*"] } }`, which overrides the security defaults at line 1755: `{ ...defaultNodeVMOptions, ...nodeVMOptions }` Taint 07: RCE Inside the nested VM, `require("child_process")` succeeds. Arbitrary commands execute as root. PoC Step 1: Start Flowise ```bash docker run -d --name flowise-poc -p 3000:3000 \ -e PORT=3000 -e DISABLE_FLOWISE_TELEMETRY=true \ flowiseai/flowise:latest # Wait ~30s for startup curl http://localhost:3000/api/v1/version # {"version":"3.1.1"} ``` Step 2: Obtain Bearer Token Register an account, then create an API key: ```bash # Register curl -s -X POST http://localhost:3000/api/v1/account/register \ -H "Content-Type: application/json" \ -d '{"user":{"email":"[email protected]","password":"Attack12345","name":"Attacker"}}' …

Related

Alias · CVE (1)

  • CVE-2026-69254 Flowise is a drag & drop user interface to build a customized large language model flow. vulnerability

Weakness · CWE (1)

  • CWE-94 Improper Control of Generation of Code weakness

References