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

Injection d'arguments dans dbt-mcp : les entrées de l'agent deviennent des options dbt

Une faille du serveur MCP de dbt corrigée le 2026-07-16 permettait à un client MCP de glisser des options globales dbt comme --profiles-dir via des paramètres d'outil, atteignant la CLI malgré shell=False.

2026-07-22 // 6 min affects: dbt-mcp, mcp-servers, dbt, ai-agents, data-pipelines

De quoi parle-t-on ?

Le 2026-07-16, dbt Labs a publié un avis de sécurité concernant une faille d’injection d’arguments dans dbt-mcp, le serveur Model Context Protocol qui permet à un agent LLM de piloter l’outil en ligne de commande dbt. Dans les versions antérieures à 1.17.1, deux paramètres d’outil contrôlés par le client MCP — la sélection de nœuds et le type de ressource — étaient transmis au sous-processus dbt sans être séparés de l’analyseur d’options de dbt. Un client MCP pouvait donc faire passer ces paramètres pour des options globales dbt et modifier la façon dont dbt s’exécutait.

Cette faille mérite l’attention non parce qu’elle est exotique, mais parce qu’elle est banale. C’est un bug classique d’injection d’arguments en ligne de commande (CWE-88) qui réapparaît dans le monde des agents, où l’« utilisateur » qui fournit ces paramètres est souvent un modèle de langage qu’un tiers peut influencer par injection de prompt indirecte.

Comment ça marche

Le serveur construisait l’invocation dbt en ajoutant les chaînes fournies par l’appelant à la liste d’arguments de subprocess.Popen(...) avec shell=False. Fixer shell=False est la bonne base : cela signifie que le système d’exploitation ne lance aucun shell, donc les métacaractères shell (;, |, backticks, $( )) ne sont jamais interprétés et ne peuvent pas enchaîner des commandes. Cette défense tient ici.

Ce que shell=False ne fait pas, c’est empêcher qu’une valeur soit lue comme une autre option par le programme que vous lancez. dbt accepte des options globales telles que --profiles-dir, --project-dir et --target. Si une valeur contrôlée par l’agent est placée dans la liste d’arguments comme un jeton distinct, l’analyseur de dbt y voit une nouvelle option plutôt qu’une donnée. Dans dbt-mcp, les paramètres de sélection de nœuds et de type de ressource s’écoulaient dans cette liste, si bien qu’un client MCP pouvait orienter dbt vers un répertoire de configuration de son choix plutôt que celui de l’exploitant.

Le modèle mental :

# shell=False bloque UNE chose, pas l'autre

  Shell metacharacter injection   ->  BLOCKED by shell=False
    (";", "|", "$(...)" never reach a shell)

  Argument / flag injection       ->  NOT blocked by shell=False
    (a controlled token is parsed by dbt as --profiles-dir / --target)

L’impact touche la confidentialité et l’intégrité, pas l’exécution de code à distance : rediriger --profiles-dir pointe dbt vers un autre profiles.yml, qui définit les connexions et les cibles de base de données. C’est pourquoi l’avis est classé en gravité moyenne, avec un vecteur local et une complexité élevée — l’attaquant doit contrôler les paramètres d’outil et disposer d’une configuration alternative accessible, mais le gain est de faire tourner dbt sur des connexions que l’exploitant n’a jamais prévues. Aucun payload fonctionnel n’est reproduit ici ; le sujet est le comportement d’analyse, pas une recette.

Pourquoi c’est important

Dans un script non agentique, « l’appelant contrôle les arguments » est souvent acceptable, car l’appelant est du code de confiance. Un serveur MCP inverse cette hypothèse. L’appelant est un LLM, et dans les déploiements réels, les arguments d’outil du LLM peuvent être façonnés par le contenu qu’il a lu — un ticket, un README, une description de table, une page web — dont chacun peut porter une injection de prompt indirecte. Un paramètre qu’un développeur imagine comme « un nom de modèle » devient un canal non fiable qui atteint un sous-processus.

Cela place le bug au cœur de la classe des wrappers d’outils d’agent qui revient sans cesse dans l’écosystème : les entrées structurées du modèle sont traitées comme des données sûres côté serveur, alors qu’elles devraient l’être comme des données adverses. Cela correspond à l’agentivité excessive et à la conception d’outils non sûrs du OWASP LLM Top 10. La leçon se généralise à tout serveur MCP qui appelle un sous-processus — dbt, git, gestionnaires de paquets, CLI cloud — où les outils porteurs d’options ne sont qu’à un jeton mal placé d’être détournés.

Défenses

Le correctif est arrivé dans dbt-mcp 1.17.1 ; la mise à jour est la première étape. Au-delà du patch, les mitigations durables pour toute cette classe sont :

  1. Terminer l’analyse des options. Insérez un séparateur -- entre les options et les données positionnelles pour que le programme enfant cesse d’interpréter les jetons suivants comme des options, ou faites passer les valeurs par des interfaces qui ne sont jamais traitées comme des options. C’est le correctif structurel le plus fiable contre l’injection d’arguments.
  2. Liste blanche, pas assainissement. Validez les paramètres contrôlés par l’agent contre un ensemble explicite de valeurs autorisées (noms de modèles connus, types de ressources connus) et rejetez tout le reste, plutôt que de tenter de retirer les caractères dangereux.
  3. Traiter les arguments d’outil MCP comme des entrées non fiables. Supposez que toute chaîne qu’un LLM transmet a pu être orientée par le contenu qu’il a ingéré. Appliquez la validation d’entrée à la frontière de l’outil comme si elle venait d’un internaute anonyme.
  4. Figer la configuration visible par le sous-processus. Définissez --profiles-dir, --project-dir et --target depuis la configuration serveur ou l’environnement, et refusez que les paramètres de requête les remplacent. Exécutez le sous-processus avec le moindre privilège et un répertoire de travail restreint.
  5. Journaliser et relire l’argv final. Émettez le vecteur d’arguments exact que produit chaque exécution d’outil, afin que des options anormales soient visibles en supervision et en réponse à incident.

Statut

ÉlémentRéférenceDateNotes
Injection d’arguments dbt-mcpCVE-2026-44968 / GHSA-xpww-f6pm-cfhq2026-07-16CVSS 6.3 (moyen), CWE-88 ; affecte dbt-mcp < 1.17.1
Version corrigéedbt-mcp v1.17.12026-07-16node_selection / resource_type n’atteignent plus dbt comme options
ClasseOWASP LLM Top 10 (2025)2025Agentivité excessive / conception d’outils non sûrs

La vulnérabilité est publiquement divulguée et corrigée ; les détails ci-dessus proviennent de l’enregistrement CVE et de l’avis de l’éditeur. L’enseignement n’est pas propre à dbt : tout outil d’agent qui ajoute des valeurs fournies par le modèle à un sous-processus doit supposer que shell=False arrête l’enchaînement de commandes mais pas l’injection d’options, et concevoir la frontière en conséquence.

Sources