Executive Summary
CVE-2025-59528 is a maximum-severity (CVSS 10.0) unauthenticated remote code execution vulnerability in FlowiseAI Flowise, a popular open-source AI agent and chatflow builder. By sending a crafted POST request to the CustomMCP node's API endpoint, an unauthenticated attacker can execute arbitrary JavaScript with full Node.js runtime privileges on the host server. With 12,000–15,000 Flowise instances publicly exposed and active exploitation confirmed in the wild, patching to version 3.0.6 or later is urgent.
1. What Is This Vulnerability?
Flowise is a drag-and-drop AI workflow builder that lets developers chain LLM calls, tool integrations, and MCP (Model Context Protocol) servers into deployable chatflows. The CustomMCP node allows users to configure a custom MCP server at runtime by supplying a JSON configuration string.
The vulnerability lives in a helper function called convertToValidJSONString inside CustomMCP.ts. This function was designed to normalize user-supplied JSON configuration, but its implementation used JavaScript's Function() constructor to evaluate the input string:
// VULNERABLE code (Flowise < 3.0.6)
function convertToValidJSONString(inputString: string): string {
return Function('return ' + inputString)();
}
The Function() constructor is equivalent to eval() — it compiles and executes arbitrary JavaScript. Because the input string came directly from an unauthenticated HTTP request body, any attacker could inject arbitrary JavaScript code rather than a benign JSON object.
Attack Vector
The vulnerable API route is:
POST /api/v1/node-load-method/customMCP
This endpoint accepts a mcpServerConfig parameter with no authentication check and no input sanitization. A malicious payload looks like this:
{
"mcpServerConfig": "{}; require('child_process').exec('id > /tmp/pwned')"
}
When the server processes this payload, convertToValidJSONString compiles and runs the injected code with full child_process access — granting the attacker read/write filesystem access, the ability to spawn shells, exfiltrate secrets, pivot to internal networks, or install persistence mechanisms.
Because the endpoint requires no credentials, no social engineering, and no prior foothold, this is a zero-click, zero-authentication RCE.
Real-World Impact
- Active exploitation was first confirmed by VulnCheck's Canary network in April 2026, with attack traffic originating from a Starlink IP address.
- A Metasploit module (PR #20705 in the rapid7/metasploit-framework repository) was merged, making exploitation trivially accessible.
- AI developer environments frequently store API keys (OpenAI, Anthropic, AWS, etc.) in environment variables — all reachable by an attacker with RCE.
2. Who Is Affected?
| Component | Affected Versions |
|---|---|
| FlowiseAI Flowise | >= 2.2.7-patch.1 and < 3.0.6 |
| Flowise (Docker) | All images based on affected versions |
| Self-hosted Flowise | Exposed to internet without reverse proxy auth |
| Cloud-deployed Flowise | Any instance without WAF / network controls |
Highest-risk configurations:
- Flowise instances directly accessible from the internet (no VPN, no reverse proxy authentication)
- Deployments with the CustomMCP node enabled in any chatflow
- Instances running as root or with elevated OS privileges
- Deployments storing LLM provider API keys, database credentials, or cloud IAM keys in environment variables
3. How to Detect It (Testing)
Manual Testing Steps
-
Identify the Flowise version — Check
Settings > Aboutin the Flowise UI, or run:curl -s http://<flowise-host>:<port>/api/v1/versionAny version string between
2.2.7-patch.1and3.0.5(inclusive) is vulnerable. -
Probe the endpoint without credentials — Send a benign test request:
curl -s -X POST http://<flowise-host>:<port>/api/v1/node-load-method/customMCP \ -H "Content-Type: application/json" \ -d '{"mcpServerConfig": "{}"}'A 200 response with no authentication challenge confirms the unauthenticated attack surface is exposed.
-
Test code execution (PoC — use only on systems you own):
curl -s -X POST http://<flowise-host>:<port>/api/v1/node-load-method/customMCP \ -H "Content-Type: application/json" \ -d '{"mcpServerConfig": "{}; process.env"}'If the response includes environment variables (e.g., API keys, secrets), the system is vulnerable.
-
Check server logs — Look for unusual POST requests to
/api/v1/node-load-method/customMCPwith complex or script-like values inmcpServerConfig.
Automated Scanning
-
Tool: Nuclei (ProjectDiscovery)
-
Template search:
nuclei -t cves/ -id CVE-2025-59528 -u http://<flowise-host> -
Expected output: Template will flag instances that respond to the unauthenticated endpoint with a valid JSON body.
-
Tool: Pentest-Tools.com Flowise RCE scanner
Available at: https://pentest-tools.com/vulnerabilities-exploits/flowise-remote-code-execution_29119 -
Tool: Metasploit
use exploit/multi/http/flowise_custom_mcp_rce set RHOSTS <target> set RPORT <port> run
Code Review Checklist
- Search codebase for
Function('return 'ornew Function(in CustomMCP.ts or related files - Verify
/api/v1/node-load-method/customMCProute requires authentication middleware - Confirm
mcpServerConfiginput is parsed withJSON5.parse()orJSON.parse(), notFunction() - Check that Flowise package.json version is
>= 3.0.6 - Verify no unauthenticated routes accept configuration objects from external callers
4. How to Fix It (Mitigation)
Step-by-Step Remediation
-
Identify your current Flowise version:
# If running via npm npx flowise --version # If running via Docker docker inspect flowise | grep -i version -
Upgrade to Flowise 3.1.1 or later (3.0.6 is the minimum safe version):
# npm / npx install npm install -g flowise@latest # Docker docker pull flowiseai/flowise:latest docker stop flowise && docker rm flowise docker run -d --name flowise -p 3000:3000 flowiseai/flowise:latest -
For Docker Compose deployments:
services: flowise: image: flowiseai/flowise:latest # was pinned to old version restart: alwaysThen run:
docker-compose pull && docker-compose up -d -
If immediate upgrade is not possible, restrict access to the vulnerable endpoint via reverse proxy:
# Nginx: block the vulnerable endpoint externally location /api/v1/node-load-method/customMCP { deny all; return 403; } -
Verify the upgrade by checking the version endpoint post-deployment.
Code Fix Example
The patch in Flowise 3.0.6 replaces the unsafe Function() call with JSON5.parse():
// BEFORE (vulnerable — Flowise < 3.0.6)
function convertToValidJSONString(inputString: string): string {
return Function('return ' + inputString)();
}
// AFTER (patched — Flowise >= 3.0.6)
import JSON5 from 'json5';
function convertToValidJSONString(inputString: string): string {
return JSON5.parse(inputString);
}
JSON5.parse() treats the input as data, not executable code. Even a malicious string like {}; require('child_process').exec('...') will throw a parse error rather than executing.
Configuration Hardening
Even on a patched system, apply defense-in-depth:
- Enable Flowise authentication: Set
FLOWISE_USERNAMEandFLOWISE_PASSWORDenvironment variables (or use SSO) so every API call requires credentials. - Reverse proxy with auth: Place Flowise behind nginx/Caddy with HTTP Basic Auth or OAuth as a second layer.
- Network segmentation: Flowise should not be directly exposed to the internet. Use a VPN or private network boundary.
- Principle of least privilege: Run the Flowise Docker container as a non-root user:
USER node - Secrets management: Store API keys in a secrets manager (AWS Secrets Manager, HashiCorp Vault) rather than plain environment variables where possible.
5. How to Test the Fix (Validation)
Regression Test Scenarios
- Scenario A: After upgrading, confirm
/api/v1/versionreturns>= 3.0.6 - Scenario B: Send the original exploit payload — confirm the server returns a parse error (4xx) rather than executing code
- Scenario C: Verify existing CustomMCP-based chatflows still function normally with legitimate JSON configurations
- Scenario D: Confirm authenticated API calls succeed while unauthenticated calls to protected routes return 401
Security Test Cases
Test Case 1: Verify RCE no longer possible
- Precondition: Flowise upgraded to 3.1.1+
- Steps:
curl -s -X POST http://<flowise-host>/api/v1/node-load-method/customMCP \ -H "Content-Type: application/json" \ -d '{"mcpServerConfig": "{}; require(\"child_process\").execSync(\"id\")"}' - Expected Result: HTTP 400 or 500 with a JSON parse error; no command output returned
Test Case 2: Confirm environment variables not leaked
- Precondition: Flowise upgraded to 3.1.1+
- Steps: Send
{"mcpServerConfig": "{}; process.env"} - Expected Result: Parse error or empty response; no env vars in body
Test Case 3: Confirm legitimate CustomMCP configs still work
- Precondition: Flowise upgraded to 3.1.1+
- Steps: Supply a valid JSON5 MCP server config object
- Expected Result: Node loads successfully, chatflow functions normally
Automated Tests
// Jest integration test — run against staging Flowise instance
const axios = require('axios');
const BASE = process.env.FLOWISE_URL || 'http://localhost:3000';
describe('CVE-2025-59528 regression', () => {
test('mcpServerConfig RCE payload is rejected', async () => {
const payload = { mcpServerConfig: '{}; require("child_process").execSync("id")' };
const response = await axios.post(
`${BASE}/api/v1/node-load-method/customMCP`,
payload,
{ validateStatus: () => true }
);
// Must not return a 200 with command output
expect(response.status).not.toBe(200);
expect(JSON.stringify(response.data)).not.toMatch(/uid=/);
});
test('valid JSON5 config is accepted', async () => {
const payload = { mcpServerConfig: '{ command: "node", args: ["server.js"] }' };
const response = await axios.post(
`${BASE}/api/v1/node-load-method/customMCP`,
payload,
{ validateStatus: () => true }
);
// Should succeed (or fail for unrelated config reasons, not parse errors)
expect([200, 400]).toContain(response.status);
});
});
6. Prevention & Hardening
Best Practices
- Never use
eval(),Function(), orvm.runInThisContext()on user-supplied input. These constructs treat strings as executable code and are the root cause of this entire vulnerability class (CWE-94). Use data parsers (JSON.parse,JSON5.parse) instead. - Enforce authentication on all API routes — even "internal" configuration endpoints. Assume any reachable endpoint will be probed. Flowise's default no-auth mode is inappropriate for internet-facing deployments.
- Pin dependency versions in production and subscribe to security advisories via GitHub Dependabot, Snyk, or your preferred SCA tool. CVE-2025-59528 was introduced in version 2.2.7-patch.1; automated alerts would have surfaced it before deployment.
- Conduct regular port scanning and attack surface reviews of your infrastructure. Tools like Shodan or Censys can tell you whether your Flowise instance is inadvertently exposed to the internet.
- Implement WAF rules to block or alert on requests containing JavaScript-like syntax (
require(,child_process,exec() in JSON body parameters.
Monitoring & Detection
Monitor for these indicators of compromise (IOCs) and behavioral anomalies:
| Signal | What to Check |
|---|---|
| Unusual child processes | Node.js spawning /bin/sh, bash, curl, wget, or python |
| Anomalous POST requests | /api/v1/node-load-method/customMCP with non-JSON body content |
| Outbound connections | Flowise making unexpected connections to external IPs on non-standard ports |
| File system writes | New executables or scripts appearing in /tmp, /var/tmp, or the app directory |
| Credential exposure | Logs showing env variable dumps or secrets in response bodies |
SIEM/alerting query (example for Elastic/Splunk):
process.parent.name:"node" AND process.name:("sh" OR "bash" OR "curl" OR "wget")
AND process.parent.args:"flowise"
Falco rule (Kubernetes/container runtime):
- rule: Flowise spawning shell
desc: Detects a shell spawned from Flowise Node.js process (possible CVE-2025-59528 exploitation)
condition: spawned_process and proc.pname = "node" and proc.name in (shell_binaries)
output: "Shell spawned by Flowise (user=%user.name cmd=%proc.cmdline)"
priority: CRITICAL
References
- CVE Entry: CVE-2025-59528 — NVD
- GitHub Security Advisory: GHSA-3gcm-f6qx-ff7p
- Patch Release: Flowise 3.0.6 Release
- BleepingComputer: Max severity Flowise RCE vulnerability now exploited in attacks
- The Hacker News: Flowise AI Agent Builder Under Active CVSS 10.0 RCE Exploitation; 12,000+ Instances Exposed
- SonicWall Analysis: FlowiseAI Custom MCP Node Remote Code Execution
- Security Affairs: Attackers exploit critical Flowise flaw CVE-2025-59528
- Metasploit Module: PR #20705 — rapid7/metasploit-framework