Breach report
Flowise CustomMCP: a config field piped straight into Function() gives CVSS 10 RCE
What happened
Flowise is a popular low-code builder for LLM agent workflows (37,000+ GitHub stars). CVE-2025-59528 is a critical RCE in its CustomMCP node, affecting versions 2.2.7-patch.1 through 3.0.5 and rated CVSS 10.0. The vulnerable endpoint, POST /api/v1/node-load-method/customMCP, accepts an mcpServerConfig parameter. Instead of safely parsing that JSON, the convertToValidJSONString function hands the untrusted input to JavaScript's Function() constructor — the equivalent of eval() — executing it as arbitrary code with Node.js runtime privileges. When API-key protection is not configured, no authentication is required; an attacker needs only network access to the endpoint (typically port 3000). The advisory noted active in-the-wild exploitation and a public proof-of-concept, with a very high EPSS score.
Root cause
Untrusted input reached a code interpreter (CWE-94). Function() compiles and runs whatever string it's given; feeding it a request-controlled config field is direct code injection. The "convert to valid JSON" helper looked like parsing but was actually execution — a dangerous lookalike. The node worked for legitimate configs, so it passed functional testing; the invariant "configuration data is never executed as code" was never checked. With auth optional and often off, one POST became a shell.
How it would have been caught
A test that posts an mcpServerConfig containing an executable payload (e.g., one that writes a marker file or triggers an outbound request) and asserts the side effect did not occur flips red against the vulnerable version. A code review flagging any path from request input to Function()/eval() catches it statically. Reproduction is a single crafted POST to the CustomMCP endpoint.
How to prevent it
- Parse data with a real parser (
JSON.parse/JSON5.parse), neverFunction()oreval(). The fix (3.0.6) does exactly this. - Require authentication on every endpoint by default — never leave RCE-capable functionality reachable anonymously.
- Keep these platforms off the public internet; run static analysis that fails the build on untrusted-input-to-interpreter flows.
The Breachwire test (red → green)
Post to /api/v1/node-load-method/customMCP (unauthenticated) with an mcpServerConfig payload that creates a marker file or makes an outbound DNS lookup, and confirm the side effect executes on the server — the RED proof of code injection. Upgrade to 3.0.6+ (parser instead of Function()) and enable API-key auth, then confirm the same request runs no code and is rejected, while valid MCP configs still load.