Flowise CustomMCP Unauthenticated Remote Code Execution via Function() Constructor (CVE-2025-59528)
by Moon-Harvest · 2026-07-06
- Severity
- Critical
- CVE
- CVE-2025-59528
- Category
- web
- Affected product
- Flowise (FlowiseAI/Flowise)
- Affected versions
- <= 3.0.5 (patched in 3.0.6)
- Disclosed
- 2026-07-06
- Patch status
- patched
Tags
References
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-06 |
| Last Updated | 2026-07-06 |
| Author / Researcher | Moon-Harvest |
| CVE / Advisory | CVE-2025-59528 |
| Category | web |
| Severity | Critical |
| CVSS Score | 10.0 |
| Status | Weaponized |
| Tags | flowise, rce, custommcp, function-constructor, javascript-injection, unauthenticated, llm, node-load-method, cwe-94 |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | Flowise (FlowiseAI/Flowise) |
| Versions Affected | <= 3.0.5 (patched in 3.0.6) |
| Language / Platform | Node.js / TypeScript backend (web application) |
| Authentication Required | No (unauthenticated; only a valid Flowise API key is needed, which may be exposed/default) |
| Network Access Required | Yes (direct HTTP access to the Flowise API endpoint) |
Summary
Flowise exposes a CustomMCP node whose loadMethod handler (/api/v1/node-load-method/customMCP) accepts a user-supplied mcpServerConfig string. On the backend, this string is passed straight into a Function() constructor inside the convertToValidJSONString helper in order to “parse” the MCP server configuration. Because Function() compiles and executes arbitrary JavaScript with the same privileges as the Node.js process, an attacker can smuggle arbitrary JavaScript — including a call into child_process — through the mcpServerConfig field. This results in unauthenticated (API-key-gated only) remote code execution on the host running Flowise.
Vulnerability Details
Root Cause
The backend’s convertToValidJSONString routine (invoked when Flowise tries to load “actions” for a CustomMCP node) evaluates the client-supplied mcpServerConfig value using JavaScript’s Function() constructor rather than a safe JSON parser (e.g. JSON.parse). Since Function() behaves like eval(), any JavaScript expression placed in this field is executed server-side with full Node.js privileges, including access to process.mainModule.require.
Attack Vector
- Send a
POSTrequest to/api/v1/node-load-method/customMCPon a reachable Flowise instance, authenticated with a valid API key (Bearer token). - Supply a JSON body with
loadMethod: "listActions"and aninputs.mcpServerConfigvalue crafted as a JavaScript IIFE expression rather than valid MCP JSON, e.g.:({x:(function(){const cp = process.mainModule.require('child_process');cp.execSync("<command>");return 1;})()}) - The backend passes this string into
Function(), which compiles and immediately executes it, callingchild_process.execSyncwith the attacker-controlled command. - The command runs with the privileges of the Flowise Node.js process, achieving RCE regardless of the response content returned to the client.
Impact
Full remote code execution on the server hosting Flowise. Because the primitive is a plain Function()/eval-style JS execution, an attacker is not limited to shell commands — any Node.js API reachable via require is available, enabling file system access, credential theft (e.g. environment variables, stored LLM API keys, database credentials), lateral movement, and persistence.
Environment / Lab Setup
Target: Flowise <= 3.0.5, reachable over HTTP/HTTPS
Attacker: Go toolchain (go run main.go) with network access to the target
Requires a valid Flowise API key (Bearer token) for the target instance
Proof of Concept
PoC Script
See
main.goin this folder.
| |
The Go PoC builds a JSON payload of the form {"loadMethod":"listActions","inputs":{"mcpServerConfig":"({x:(function(){const cp = process.mainModule.require('child_process');cp.execSync(\"<command>\");return 1;})()})"}} and POSTs it (with Authorization: Bearer <api-key>) to <target-base-url>/api/v1/node-load-method/customMCP. A 200 OK response (even one stating “No available actions, please check your API key and refresh”) indicates the injected command was likely executed server-side before the load-method handler returned.
Detection & Indicators of Compromise
Signs of compromise:
- Unexpected child processes spawned by the Flowise Node.js process
- New/unexplained files created by the Flowise service account (e.g. test artifacts like
/tmp/pwned) - Flowise logs containing JavaScript expressions instead of well-formed
mcpServerConfigJSON - Outbound connections or reverse shells originating from the Flowise host shortly after a
node-load-method/customMCPrequest
Remediation
| Action | Detail |
|---|---|
| Primary fix | Upgrade Flowise to version 3.0.6 or later, which addresses the unsafe Function()-based parsing of mcpServerConfig |
| Interim mitigation | Restrict network access to the Flowise API, rotate/limit exposure of API keys, and monitor/alert on node-load-method/customMCP requests with non-JSON mcpServerConfig payloads |
References
Notes
Mirrored from https://github.com/Moon-Harvest/CVE-2025-59528 on 2026-07-06.
| |