FlawOpen

flawopen.com/Teardowns/cve-2026-105697-langflow-mcp-stdio-command-injection

● CVE-2026-105697 · CVSS 9.9[1] · Critique
Recherche · FlawOpen

CVE-2026-105697 : injection de commandes MCP dans Langflow

Avant la version 1.10.3, Langflow transmettait la configuration MCP stdio à un processus lancé par un shell. Sur une instance exposée avec LANGFLOW_AUTO_LOGIN=true, un attaquant pouvait obtenir un jeton sans identifiants ; avec la connexion automatique désactivée, un utilisateur authentifié non administrateur pouvait encore atteindre l’exécution de commandes sur l’hôte. La version 1.10.3 valide tous les chemins, juste avant le lancement compris, et démarre le programme sans shell.[1], [2], [3]

Vecteur CVSSCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H[1]
💡 Explication en Langage Simple (ELI5)

Imaginez un employé qui reçoit une phrase dont la ponctuation peut changer la tâche : un signe peut transformer une consigne de livraison en un second ordre. Langflow transmettait la commande configurée à un shell qui interprète cette syntaxe comme une instruction de contrôle, au lieu de traiter l’exécutable et ses arguments comme des données distinctes. Le correctif valide la commande autorisée et lance directement le programme, sans shell.[1], [2]

Concepts Clés et Termes

Transport MCP stdio
Lance un serveur MCP comme processus enfant local et échange des messages par l’entrée et la sortie standard.[1], [2]
Injection de commandes (CWE-78)
Un texte influencé de l’extérieur modifie la commande système transmise au shell ou au lanceur de processus.[1], [5]
Point d’exécution
Chemin final qui crée un processus ; la validation doit s’y appliquer même si l’API a déjà effectué des contrôles.[1], [2]
Configuration intégrée flow/tweak
Configuration MCP intégrée à un flow ou à une surcharge d’exécution plutôt que créée par l’API des paramètres.[1], [2]

Correspondances de référentiels

  • Référence CWE pour la faiblesse décrite dans ce guide : CWE-78

Analyse de Cause Racine

Avant la version 1.10.3, la configuration MCP stdio concaténait la commande et les arguments en une chaîne, puis lançait bash -c avec cette chaîne. L’API de configuration a reçu une liste d’autorisation et des contrôles des arguments et de l’environnement en version 1.9.0, mais les configurations MCP Tools intégrées aux flows ou aux tweaks pouvaient contourner la validation du modèle, car le point d’exécution n’appliquait aucune politique commune. Langflow 1.10.3 centralise la validation dans lfx.base.mcp.security.validate_mcp_stdio_config, l’applique à l’API, aux flows, aux tweaks, au composant historique et juste avant la création du processus, puis supprime le shell intermédiaire. CVE-2026-105697 correspond à CWE-78, CVSS 3.1 9.9. Lorsque la connexion automatique est désactivée, un utilisateur authentifié non administrateur pouvant configurer ou exécuter le chemin MCP reste nécessaire ; la connexion automatique par défaut peut exposer des instances de développement sans identifiants.[1], [2], [4], [5]

Déroulement de l'Attaque Étape par Étape

Étape 1

Un utilisateur atteint une voie de configuration MCP

L’avis décrit l’accès via les paramètres MCP ou un flow utilisant le composant MCP Tools. Sur une instance exposée conservant la valeur de développement LANGFLOW_AUTO_LOGIN=true, un attaquant pouvait obtenir un jeton sans identifiants. Si la connexion automatique est désactivée, un utilisateur authentifié non administrateur peut tout de même suffire.[1]

Étape 2

La configuration arrive à la préparation du processus

La commande et les arguments deviennent command_str pendant la préparation d’une connexion MCP stdio.[1]

Étape 3

Le shell interprète la chaîne

Avant 1.10.3, le chemin utilisait bash -c ; l’exécution avait lieu lors de la tentative de connexion, avant la réussite du handshake MCP.[1]

Étape 4

Les contrôles à l’entrée sont incomplets

La version 1.9.0 valide les paramètres REST, mais les flows et tweaks peuvent contourner cette validation du modèle.[1]

Étape 5

Le processus hôte utilise les privilèges de Langflow

La commande s’exécute sous le compte du service Langflow. L’interface peut néanmoins signaler l’échec du démarrage MCP.[1]

Étape 6

1.10.3 ferme le point d’exécution

Une politique commune valide chaque entrée et juste avant la création du processus ; le programme démarre sans shell.[1], [2]

Code Source : Vulnérable vs Sécurisé

L’extrait vulnérable montre le mode de lancement via shell décrit dans l’avis ; ce n’est pas un exploit exécutable. L’extrait corrigé résume la conception de la version 1.10.3 : une politique commune valide la configuration à chaque entrée et juste avant la création du processus, tandis que l’API reçoit séparément l’exécutable et les arguments. Le lancement direct supprime l’interprétation par le shell, mais ne rend pas automatiquement sûrs tous les exécutables ou paquets autorisés ; les opérateurs doivent aussi appliquer des contrôles de provenance des paquets et d’isolation adaptés.[1], [2]

Extrait source: lfx/base/mcp/util.py — extraits de code ciblés

IMPLÉMENTATION VULNÉRABLE
# Forme de lancement concernée selon l’avis (extrait ciblé) :
server_params = StdioServerParameters(
    command="bash",
    args=["-c", f"exec {command_str}"],
    env=env_data,
)
PATCH SÉCURISÉ ET ROBUSTE
# Version simplifiée inspirée du code 1.10.3 : valider la politique, puis lancer directement le processus.
command_parts = shlex.split(command_str)
if not command_parts:
    raise ValueError("MCP stdio command is required")
command, args = command_parts[0], command_parts[1:]
validate_mcp_stdio_config(command, args, env_data)  # Repeat at the execution boundary.
server_params = StdioServerParameters(
    command=command,
    args=args,
    env=env_data,
)  # No shell wrapper. The shared validator rejects disallowed configurations.

Liste de Contrôle de Sécurité pour l'Ingénierie

Sources