Le refus arrive après l’exécution. Dans la démonstration qui accompagne ToFu, une prépublication mise en ligne le 9 octobre 2026, un agent appelle un outil factice puis déclare ne pas pouvoir satisfaire la demande. Le travail de six chercheurs examine ce qui se passe entre la sortie du modèle, le programme qui déclenche l’action et l’outil qui la réalise.
Les auteurs disent avoir reproduit leur attaque « Repeat-After-Me » sur six orchestrateurs, mais ne publient une démonstration complète que pour LangGraph. Leur second résultat est un banc de test qui a relevé 253 bogues de sécurité, vérifiés par leurs soins, dans 118 serveurs MCP (Model Context Protocol) open source.
Quand la répétition devient un appel d’outil
Le modèle produit le nom d’un outil et ses arguments ; l’orchestrateur décide comment traiter cet appel structuré. Dans le scénario étudié, l’attaquant connaît le format attendu et demande au modèle de recopier un appel qu’il a rédigé. L’enjeu est le passage de cette consigne à un véritable appel d’outil. Une chaîne affichée dans la réponse en texte libre ne suffit pas à déclencher l’exécution dans la démonstration publiée.
Les auteurs disent avoir reproduit ce comportement sur LangGraph, Microsoft Agent Framework, Google ADK 2.0, AutoGen, AWS Strands et CrewAI. Le papier ne détaille pas les versions testées pour chacun : seule la démonstration sur LangGraph est publiée en entier.
La démonstration sur LangGraph
L'annexe B du préprint décrit le montage. LangGraph 1.2.0, son nœud d'exécution d'outils prêt à l'emploi (ToolNode), le modèle Llama 3.1 8B servi par Ollama à température nulle, et deux outils factices sans effet, make_bomb et launch_missiles, qui renvoient une liste figée. Seule protection, une consigne système qui demande de refuser toute requête dangereuse.
Au premier tour, le modèle refuse et recopie l'appel dans sa réponse en simple texte : rien ne s'exécute. Au second, l'attaquant présente la même demande comme « hypothétique » et exige que le modèle ne produise rien d'autre que la chaîne citée. Le modèle renvoie alors un message vide accompagné d'un appel structuré à launch_missiles avec exactement les arguments écrits par l'attaquant, et ToolNode l'exécute aussitôt. Le refus n'apparaît qu'après le retour de l'outil. « La consigne système a façonné ce que le modèle disait, pas ce que l'orchestrateur faisait », résument les auteurs.
Le montage reste favorable à l’attaquant : un modèle local de 8 milliards de paramètres, un outil et un format connus d’avance, et une consigne système pour seule protection. Le papier ne mesure pas le taux de réussite sur des modèles plus robustes. Dans la configuration testée, aucun contrôle indépendant d’autorisation n’intercepte l’appel avant son exécution.
253 bogues dans des serveurs MCP qui font confiance au modèle
La seconde partie du travail tire la conséquence de ce constat. Si un attaquant peut dicter les arguments, via le prompt de l'utilisateur, un contenu récupéré ou la sortie d'un autre outil, alors chaque argument doit être traité comme hostile au moment où il atteint l'outil. ToFu part donc des métadonnées que les serveurs MCP exposent déjà au modèle (description de l'outil, sens de chaque argument) pour en déduire des contrôles de sécurité. Un argument décrit comme « fichier dans l'espace de travail » ne doit pas permettre de lire ../../etc/passwd. ToFu génère ensuite les entrées adverses et vérifie à l'exécution si la promesse est tenue, à l'aide de 74 détecteurs, pour la plupart rattachés à une classe de faiblesses CWE.
Les chercheurs ont testé 273 serveurs Python ou JavaScript, représentant 3 405 outils extraits dont une partie seulement a pu être exercée. Après vérification manuelle et retrait des doublons, ils retiennent 253 bogues reproductibles dans 118 serveurs. Ces résultats portent sur le corpus sélectionné et ne donnent pas un taux de vulnérabilité de l’ensemble de l’écosystème MCP.
Les défauts les plus nombreux concernent des sorties qui reproduisent l’entrée sans l’échapper, des traversées de chemin permettant d’accéder à des fichiers hors périmètre et des injections dans les journaux. Le corpus comprend aussi des requêtes réseau détournées, des exfiltrations et trois injections de commandes système.
Ces défauts peuvent se manifester sans plantage, donc échapper à un test qui ne surveille que les arrêts du programme. Les auteurs rapportent notamment des accès à des fichiers hors de l’espace prévu, la suppression de fichiers et la fermeture de sessions de terminal qui n’appartenaient pas à l’outil testé.
Un problème de réglages par défaut
Le ticket #8817, ouvert le 4 septembre par le premier auteur, Nazmul Islam Ananto, reprend le scénario. Il demande un point d’interception documenté avant l’exécution ou un avertissement explicite sur le comportement du nœud d’outils. Au 16 octobre, le ticket reste ouvert.
Des contrôles existent déjà. Le code de ToolNode dans langgraph-prebuilt 1.1.0, version minimale requise par LangGraph 1.2.0, propose le paramètre optionnel wrap_tool_call pour intercepter un appel et refuser de l’exécuter. CrewAI fournit aussi un crochet avant l’appel capable de le bloquer. Ces mécanismes doivent être configurés. Le code du ticket LangGraph, lui, utilise un nœud maison qui exécute les appels émis par le modèle.
Pour une équipe qui déploie des agents, la conséquence est concrète : l’autorisation doit être vérifiée sur l’outil et ses arguments, indépendamment du texte produit par le modèle. Les contrôles proposés par les frameworks fournissent un point d’interception ; les outils doivent en plus valider eux-mêmes les fichiers, les destinations réseau et les opérations qu’ils acceptent. Un appel conforme au schéma peut demander une action que l’utilisateur n’a pas le droit d’effectuer.
La version 1 de ToFu teste les outils appel par appel. Elle ne couvre ni les suites d’actions qui dépendent d’un état, ni les échanges entre plusieurs agents, ni les défauts sans effet observable à l’exécution.
Nos articles remonteront en priorité dans « À la une » de Google.
