GHSA-9rvc-vf7m-pgm2: FlowiseAI: Authenticated Host RCE via POST /api/v1/node-custom-function and NodeVM Sandbox Escape
Summary`POST /api/v1/node-custom-function` lacks route-level authorization, allowing any authenticated user or API key to submit arbitrary JavaScript to the `Custom JS Function` node.When `E2B_APIKEY` is not configured — the common deployment case — Flowise executes this code inside a `NodeVM` sandbox. This sandbox can be escaped, allowing an attacker to reach the host `process` object and execute system commands via `child_process`.The result is authenticated remote code execution on the Flowise server host. CVSS v3.1: `AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H` = **9.9 Critical**.DetailsTwo distinct security boundaries are violated.**1. Missing route-level authorization**`packages/server/src/routes/node-custom-functions/index.ts` registers the endpoint with no permission middleware:Other sensitive routes in the same codebase use explicit permission gates:Global `/api/v1` authentication still applies, so this is not unauthenticated — but any valid session or API key reaches the endpoint without further restriction.**2. NodeVM sandbox escape**The endpoint forwards `body.javascriptFunction` through the following chain:`packages/components/src/utils.ts` only uses the external E2B sandbox when `E2B_APIKEY` is set. Otherwise it silently falls back to `@flowiseai/nodevm`:Flowise explicitly frames this as a sandboxed execution path — the helper is named `createCodeExecutionSandbox`, its inline comment reads `Execute JavaScript code using either Sandbox or NodeVM`, and the NodeVM instance is configured with `eval: false`, `wasm: false`, and mocked HTTP clients. The sandbox is a real declared security boundary, not incidental isolation.These controls do not prevent escape. The payload abuses an exception path where an `Error` object escapes the NodeVM boundary. Because the error originates from the host runtime, its constructor chain resolves to the outer Node.js realm. This allows recovery of the host `Function` constructor (`e.constructor.constructor`), which can then access `process` and built-in modules such as `child_process`:The NodeVM fallback is the practical default. `packages/server/.env.example` and `CONTRIBUTING.md` do not require `E2B_APIKEY` for custom JS execution, so most deployments are affected.PoC**Standalone verification** (run from the repository root with `E2B_APIKEY` unset):Confirmed output:**HTTP trigger** (requires a valid API key or session):ImpactAny authenticated Flowise user or holder of a standard API key can execute arbitrary commands as the Flowise server process. This includes reading environment variables and secrets, arbitrary filesystem access, outbound network requests from the host, and a foothold for persistence or lateral movement.The NodeVM fallback is the default for any deployment without `E2B_APIKEY` configured, which covers the majority of self-hosted instances.**Recommended remediation:**Add explicit permission gating to `POST /api/v1/node-custom-function` using the existing `checkPermission` middleware pattern.Fail closed if `E2B_APIKEY` is absent — do not silently downgrade to NodeVM for untrusted code execution.Restrict this endpoint from generic API key access.
CVSS v4.0: 9.4