Chaîne d'attaque critique non authentifiée menant à une RCE complète dans FlowiseAI (CVE-2025-58434 + CVE-2025-59528)
Prise de contrôle de compte non authentifiée enchaînée avec exécution de code à distance contre FlowiseAI
<= 3.0.5.
Compromission complète du conteneur en moins de 5 secondes, aucune information d'identification requise.
Gauche : page de connexion FlowiseAI — Droite : shell root via CVE-2025-59528 · uid=0(root)
Cet exploit enchaîne deux vulnérabilités critiques indépendantes en une seule attaque entièrement automatisée. Aucune des deux vulnérabilités ne garantit à elle seule une compromission complète — mais ensemble, elles forment une chaîne d'attaque complète allant de zéro identifiant à un shell root à l'intérieur d'un conteneur Docker.
[Aucun identifiant]
│
▼
① Abuser du point de terminaison forgot-password (aucune authentification requise)
│ → Le serveur répond avec le jeton de réinitialisation de la victime en texte clair
▼
② Soumettre le jeton au point de terminaison reset-password
│ → L'attaquant contrôle le mot de passe administrateur
▼
③ Connexion + récupération de la clé API Bearer
│ → Session authentifiée complète établie
▼
④ Envoyer une charge utile JavaScript via le nœud customMCP
│ → Le serveur l'évalue via le constructeur Function()
▼
[Shell root à l'intérieur du conteneur Docker]
Ce qui le rend sans interaction : à aucun moment la victime ne reçoit un email, ne voit une alerte de connexion ou ne déclenche un événement visible. L'attaque est entièrement côté serveur.
CVSS 3.1 : 9.8 Critique — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Affecté : FlowiseAI <= 3.0.5 (cloud + auto-hébergé)
Avis : GHSA-wgpv-6j63-x5ph
FlowiseAI a un concept de requêtes « internes » — des appels API entre ses propres services — identifiées par l'en-tête HTTP x-request-from: internal. Le point de terminaison /api/v1/account/forgot-password utilise cet en-tête pour sauter complètement l'authentification et renvoyer une réponse différente, plus détaillée que celle qu'il renverrait pour des appelants externes.
Le problème : cet en-tête n'est ni validé ni restreint de quelque façon que ce soit. N'importe quel attaquant sur Internet peut l'envoyer. Quand il le fait, au lieu de déclencher un email de réinitialisation de mot de passe, l'API répond avec l'enregistrement complet de l'utilisateur — y compris un tempToken actif qui peut être immédiatement utilisé pour définir un nouveau mot de passe.
Normalement, un flux de réinitialisation de mot de passe ressemble à :
L'utilisateur demande la réinitialisation → Le serveur génère un jeton → Le jeton est envoyé par EMAIL → L'utilisateur clique sur le lien → Mot de passe changé
Ici, le serveur saute complètement l'étape d'envoi d'email et place le jeton directement dans le corps de la réponse HTTP. L'attaquant l'intercepte et passe directement à l'étape de réinitialisation — aucun accès à l'email nécessaire.
POST /api/v1/account/forgot-password HTTP/1.1
Host: <target>
Content-Type: application/json
x-request-from: internal
{"user": {"email": "[email protected]"}}
201 — enregistrement complet de l'utilisateur exposé{
"user": {
"email": "[email protected]",
"credential": "$2a$05$hVtF9EKL0lI1qqrvwTD3QeFMzVlvtk8fAKX...",
"tempToken": "N5oXQ9C99h0zMNNGWLvoE4buMvcdXN32...",
"tokenExpiry": "2026-04-11T21:37:03.063Z",
"status": "active"
}
}
Le tempToken est ensuite soumis directement au point de terminaison de réinitialisation — aucune interaction par email, aucun CAPTCHA, aucune limite de débit.

CVSS 3.1 : 10.0 Critique — AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
Affecté : FlowiseAI <= 3.0.5
Avis : GHSA-3gcm-f6qx-ff7p
FlowiseAI permet aux utilisateurs de définir des nœuds MCP (Model Context Protocol) personnalisés avec une configuration serveur fournie sous forme de chaîne JSON. En interne, la plateforme a besoin d'analyser cette configuration — et elle le fait en utilisant le constructeur Function() de JavaScript, qui est fonctionnellement équivalent à eval().
La chaîne de configuration atteint le point de chute complètement non nettoyée :
// packages/components/nodes/tools/MCP/CustomMCP/CustomMCP.ts — ligne 262
const result = Function('return ' + mcpServerConfig)();
// ↑ entrée utilisateur non nettoyée — exécution JS arbitraire
Function() est aussi dangereux que eval()Function('return ' + code)() fait ce qui suit :
code comme corpsCela donne à l'attaquant un contexte complet d'exécution JavaScript avec accès à process, require, child_process, et à l'ensemble de l'environnement d'exécution Node.js — pas un bac à sable.
HTTP POST /api/v1/node-load-method/customMCP
└─ body.inputs.mcpServerConfig ← chaîne contrôlée par l'attaquant
└─ substituteVariablesInString() ← aucun filtrage, passe à travers
└─ convertToValidJSONString() ← aucun filtrage, passe à travers
└─ Function('return ' + input)() ← le code arbitraire s'exécute ici