système : OPÉRATIONNEL
← retour à tous les hacks
AGENTS CRITICAL NEW

Langroid SQLChatAgent : de l'injection prompt-vers-SQL à la RCE (CVE-2026-25879)

Divulguée le 1er juin 2026, la CVE-2026-25879 (CVSS 9.8) permet à un agent SQL victime d'injection de prompt d'exécuter des primitives comme COPY FROM PROGRAM, transformant un chatbot en exécution de code sur l'hôte de la base.

2026-06-02 // 7 min affects: langroid<0.63.0, postgresql, mysql, mssql

De quoi s’agit-il ?

Le 1er juin 2026, la CVE-2026-25879 a été publiée pour Langroid, un framework Python de construction d’applications pilotées par LLM. L’avis (GHSA-mxfr-6hcw-j9rq, relu par GitHub le 27 mai 2026) classe le problème en 9.8 Critique (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H) et le rattache aux faiblesses CWE-89 (injection SQL) et CWE-94 (injection de code).

Le composant concerné est SQLChatAgent, un agent intégré qui permet de poser des questions en langage naturel sur une base de données. L’agent demande à un LLM de traduire la question en SQL, puis exécute ce SQL. Comme le SQL est produit par un modèle qui peut être détourné par injection de prompt, un attaquant capable de façonner l’entrée de l’agent — directement, ou indirectement via des données que l’agent relit depuis la base — peut amener l’agent à émettre et exécuter des requêtes que l’opérateur n’avait jamais prévues. Les versions antérieures à 0.63.0 sont vulnérables.

Comment ça marche

La cause racine est une frontière de confiance qui n’existe pas : la sortie du modèle est exécutée comme une commande privilégiée, sans aucune liste blanche entre la génération et l’exécution. Le SQL généré par le LLM est transmis directement au pilote de la base (run_query dans sql_chat_agent.py, d’après la trace d’appel de l’avis) : tout ce que le modèle peut être amené à écrire, la base tentera de l’exécuter.

L’escalade de la « simple injection SQL » vers l’« exécution de code à distance » provient du rôle de la base de données, pas de Langroid lui-même. Lorsque la connexion utilise un rôle disposant de privilèges d’exécution de code ou d’accès au système de fichiers, du SQL ordinaire devient un shell :

PostgreSQL : COPY ... FROM PROGRAM '<command>'   (needs pg_execute_server_program / superuser)
MySQL      : SELECT ... INTO OUTFILE / LOAD_FILE  (needs FILE privilege)
MSSQL      : EXEC xp_cmdshell '<command>'         (needs xp_cmdshell enabled)

Ces primitives sont des fonctionnalités DBA documentées de longue date, pas un nouvel outillage d’attaque. La nouveauté tient au vecteur de livraison : au lieu d’une injection web classique via un champ paramétré, le « point d’injection » est un prompt conversationnel, et ce qui est dupé est un modèle de langage. La preuve de concept publique présente une instruction malveillante comme un « test d’intégration » anodin et dissimule la requête cible derrière une étape d’encodage, afin que la demande paraisse n’être qu’un travail de décodage inoffensif plutôt qu’une commande évidente. Nous ne reproduisons délibérément pas le payload fonctionnel ici ; c’est le mécanisme qui compte pour la défense, et la PoC du rapporteur exécute id via COPY ... FROM PROGRAM uniquement pour prouver que la primitive se déclenche.

C’est la troisième RCE du même framework à suivre un même schéma : un outil d’agent exécute du code contrôlé par le modèle contre un backend puissant. Elle a été précédée par la CVE-2025-46724 (injection de code pandas_eval dans TableChatAgent) et son contournement de WAF de février 2026, la CVE-2026-25481 (9.4 Critique). Les listes de blocage ont été contournées ; la variante SQL n’a fait que déplacer le même problème vers la couche base de données.

Pourquoi c’est important

Une fonction « discuter avec votre base » en lecture seule est précisément le genre d’intégration que les équipes déploient sans modèle de menace, parce qu’elle semble en lecture seule. La CVE-2026-25879 démontre le contraire : avec AV:N/AC:L/PR:N/UI:N, un acteur distant non authentifié capable d’atteindre l’entrée de l’agent — un chatbot de support, un pipeline RAG qui ingère des documents contrôlés par l’attaquant, un assistant de ticketing — peut atteindre le shell de l’hôte de la base si la connexion est surprivilégiée.

Le chemin indirect est le plus dangereux. Même lorsque les utilisateurs finaux sont de confiance, toute donnée que l’agent relit peut porter des instructions. Une ligne empoisonnée, un PDF forgé, un champ de commentaire ou une page web scrappée que l’agent résume ensuite peuvent tous devenir le vecteur d’injection : la surface d’attaque devient l’intégralité du corpus que l’agent manipule, pas seulement la zone de saisie.

La récurrence sur trois CVE est la vraie leçon. Le défaut est architectural : tant qu’un framework laisse la sortie d’un LLM atteindre un eval, un shell ou une session SQL privilégiée sans verrou strict, corriger un outil ne fait que déplacer la faille. Quiconque construit des agents qui exécutent du code ou des requêtes générés par un modèle doit présumer qu’il hérite de cette classe de problème, et pas seulement de cette CVE.

Défenses

  1. Mettez à niveau vers Langroid 0.63.0 ou supérieur. Le correctif fait passer SQLChatAgent par défaut à une liste blanche d’instructions analysées avec sqlglot, limitée au SELECT, doublée d’une liste de blocage de motifs dangereux sensible au dialecte. L’ancien comportement ne revient que si vous positionnez explicitement allow_dangerous_operations=True — laissez-le désactivé sauf déploiement pleinement de confiance.
  2. Appliquez le moindre privilège au rôle de la base. C’est le contrôle qui casse la RCE indépendamment des bugs du framework. Donnez à l’agent un rôle dédié en lecture seule ; révoquez FILE (MySQL), tenez-le à l’écart du superutilisateur PostgreSQL / pg_execute_server_program, et assurez-vous que xp_cmdshell est désactivé (MSSQL). Dans cette CVE, la RCE dépend entièrement des privilèges du rôle.
  3. Validez le SQL généré avant exécution. Analysez la sortie du modèle avec un véritable parseur SQL, n’autorisez que les types d’instructions prévus, et rejetez les verbes DDL/administratifs (COPY ... FROM PROGRAM, CREATE FUNCTION, INTO OUTFILE, EXEC). Ne transmettez jamais du texte LLM à un pilote sans l’analyser.
  4. Isolez le backend. Faites tourner la base (et tout outil d’exécution de code) dans un segment réseau sans accès sortant ni identifiants permettant de pivoter, afin qu’une injection réussie reste dans un périmètre confiné.
  5. Traitez les données ingérées comme non fiables. Pour les agents RAG et outillés, le canal indirect importe le plus : assainissez et bornez le contenu récupéré, et ne laissez pas des documents résumés déclencher des actions privilégiées sans validation humaine.
  6. Journalisez et auditez les appels d’outils. Enregistrez le SQL exact exécuté à chaque tour d’agent. Les instructions contenant PROGRAM, OUTFILE, xp_cmdshell ou un DDL inattendu sont des alertes à fort signal.

État des lieux

ÉlémentRéférenceDateNotes
Avis GHSAGHSA-mxfr-6hcw-j9rq2026-05-27Relu par GitHub, prompt-vers-SQL → RCE dans SQLChatAgent
Publication CVENVD / CVE2026-06-01CVSS 9.8, CWE-89 + CWE-94
Versions affectéeslangroid< 0.63.0RCE quand le rôle DB autorise les primitives code/fichier
Version corrigéelangroid0.63.0Liste blanche SELECT ; opt-out via allow_dangerous_operations
RCE liées antérieuresCVE-2025-46724 / CVE-2026-254812025 → fév. 2026Injection pandas_eval + contournement de WAF dans TableChatAgent

Le titre n’est pas « un LLM a écrit du mauvais SQL ». C’est qu’un agent conversationnel doté d’une connexion privilégiée à une base est un shell distant qui attend la bonne phrase — et le correctif qui tient, c’est le moindre privilège plus un parseur entre génération et exécution, pas un prompt plus malin.

Sources