Pourquoi MCP est une surface d'attaque qu'aucun audit classique ne couvre
Le Model Context Protocol publié par Anthropic en novembre 2024 a fait passer les agents LLM d'un mode isolé à un mode connecté à des outils externes. En 2026, un agent Claude Desktop, Claude Code, ou n'importe quel client compatible MCP peut, via un simple fichier de configuration JSON, manipuler un système de fichiers, interroger une base de données, appeler l'API GitHub, exécuter des recherches web, contrôler un navigateur headless, ou orchestrer plusieurs de ces capacités en chaîne.
Cette ouverture est extraordinaire pour la productivité. Elle ouvre aussi une surface d'attaque que la grande majorité des audits sécurité classiques ne couvre pas, pour une raison simple : un serveur MCP n'est pas une API REST traditionnelle. C'est un fournisseur de capacités exécutables consommées par un agent partiellement non-déterministe, dont les décisions sont influencées par des entrées qui ne viennent pas toujours de l'utilisateur — elles viennent aussi des sorties d'autres outils, du contenu web récupéré, ou du contenu de fichiers ouverts par l'agent lui-même.
Sur les six dernières semaines, j'ai audité douze serveurs MCP open source largement déployés (filesystem, fetch, github, brave-search, postgres, sqlite, slack, sequential-thinking, time, memory, puppeteer, gdrive) avec une méthodologie défensive standard. Cinq patterns récurrents émergent. Aucun n'est une faille du protocole MCP en lui-même — ce sont des erreurs d'implémentation et de modèle de confiance qui se répètent à travers l'écosystème, souvent dans des serveurs maintenus par des équipes sérieuses.
L'objectif de cette note est défensif : permettre aux équipes qui intègrent MCP en production d'évaluer leur posture et de durcir leur configuration. Aucun payload prêt à l'emploi n'est publié. Les exemples sont volontairement abstraits.
Méthodologie d'audit
Pour chaque serveur, j'ai appliqué le pipeline suivant :
- Revue statique du code source : recherche des points où des entrées externes (paramètres tool, contenu fetché, contenu fichier) atteignent une fonction sensible (
exec,spawn,readFile, opérations SQL, sérialisation). - Mapping des tool definitions : extraction des descriptions de tools, des schémas de paramètres, et des chaînes de format injectées dans le prompt système de l'agent.
- Test d'isolation : observation du périmètre réel du serveur — sandbox de processus, restrictions filesystem, scope réseau, persistance des secrets.
- Fuzzing structuré des paramètres tools avec des entrées sémantiquement valides mais bordant le contrat (paths relatifs, encodages alternatifs, séparateurs OS, sémaphores SQL).
- Test de prompt injection indirecte : insertion de marqueurs dans les sources de données externes (fichiers, pages web, lignes de base) pour observer la propagation dans le contexte agent.
Tous les tests ont été conduits sur des instances locales isolées des serveurs, sans interaction avec des API tierces en production. Les findings ont été remontés en privé aux mainteneurs concernés lorsque l'impact concret méritait une coordination.
Pattern 01Tool description injection
Le premier pattern observé concerne la chaîne par laquelle les descriptions de tools arrivent dans le prompt système de l'agent. Quand un client MCP s'initialise, il appelle tools/list sur chaque serveur configuré et insère le résultat dans le contexte de l'agent. Cette insertion est littérale : la description du tool, ses paramètres, et leurs descriptions, sont injectés tels quels.
Or, dans plusieurs serveurs audités, ces descriptions sont générées dynamiquement à partir de sources externes — un schéma OpenAPI fetché à l'init, une définition de base de données introspectée, un fichier de configuration utilisateur, des en-têtes de fichiers. Si une de ces sources est compromise ou simplement contrôlée par un tiers (cas du serveur postgres qui décrit chaque table comme un tool, ou du serveur github qui peut introspector des dépôts arbitraires), un attaquant peut faire apparaître dans le prompt système des instructions qui ressemblent à des descriptions de tools mais sont en réalité des consignes pour l'agent.
Exemple abstrait : un nom de colonne dans une table PostgreSQL contrôlée par un tiers peut contenir des caractères de formatage et du texte d'instruction. Quand le serveur génère la description du tool de query, ce contenu est concaténé sans neutralisation dans le prompt système.
L'agent reçoit des instructions qui paraissent venir d'Anthropic ou du développeur du client, mais viennent en réalité d'une source non-fiable. Cela contourne toutes les hypothèses de confiance qui sous-tendent la séparation system prompt / user prompt / tool output.
Le pattern défensif applicable est strict : les descriptions de tools doivent être figées au moment du packaging du serveur, pas générées à partir de données dynamiques. Si une génération dynamique est nécessaire (cas légitime pour les serveurs base de données), les chaînes injectées doivent être neutralisées au minimum : strip des caractères de contrôle, troncature agressive, et encapsulation dans un délimiteur typé (par exemple, des balises XML que l'agent est entraîné à traiter comme du contenu non-interprétable).
Pattern 02Authentification absente sur les serveurs locaux exposés
Le second pattern est plus prosaïque mais d'impact direct. La grande majorité des serveurs MCP open source sont conçus pour tourner en local, sur la machine de l'utilisateur final, communiquant avec le client via stdio ou un socket Unix. Le modèle de confiance implicite est : si le processus tourne, c'est que l'utilisateur l'a démarré, donc c'est l'utilisateur qui l'utilise.
Cette hypothèse tient dans 80% des cas. Elle tombe dans deux configurations courantes :
- Serveurs exposés en HTTP sur localhost sans authentification. Plusieurs serveurs audités exposent un endpoint HTTP par défaut sur
127.0.0.1:port. Tout processus tournant sous le même UID peut alors invoquer leurs tools. Sur un poste développeur partagé, ou simplement sur une machine où tourne un navigateur, n'importe quel onglet malveillant peut, via une requête XHR verslocalhost, déclencher des opérations filesystem ou des appels API authentifiés. - Serveurs exposés via Docker avec des bindings réseau non-restreints. Plusieurs guides d'installation pour intégrations entreprise recommandent
-p 8080:8080ou équivalent, exposant le serveur à toute la LAN sans authentification.
Le pattern défensif est connu mais sous-appliqué : tout serveur MCP qui n'utilise pas stdio pour son canal de communication doit imposer une authentification — au minimum un token partagé généré au démarrage et passé via une variable d'environnement au client, idéalement une session signée avec rotation.
Pattern 03Command et path injection dans les paramètres de tools
Le troisième pattern est familier aux pentesters web mais se manifeste différemment dans le contexte MCP. Beaucoup de serveurs implémentent des tools qui exécutent des commandes shell ou des opérations filesystem à partir de paramètres fournis par l'agent. Le risque n'est pas l'agent lui-même — il est raisonnablement instruit pour ne pas injecter des séquences shell — mais la chaîne d'injection indirecte :
- L'agent lit un fichier, une page web, ou une ligne de base de données.
- Le contenu de cette source contient une instruction qui ressemble à une intention utilisateur légitime.
- L'agent compose un appel tool en intégrant ce contenu dans un paramètre.
- Le serveur MCP, faisant confiance à l'agent, passe le paramètre à
exec,spawn, ou ouvre un path relatif.
Trois sous-patterns observés sur les serveurs audités :
Path traversal classique sur les serveurs filesystem qui ne canonicalisent pas les paths avant de vérifier qu'ils sont dans le scope autorisé. Un paramètre du type ../../../etc/passwd contourne la vérification dans plusieurs implémentations qui se contentent d'un startsWith sur la string brute.
Argument injection sur les serveurs qui appellent une CLI externe avec un paramètre fourni par l'agent comme argument positionnel. Sans usage de -- ou d'array-style execution, un paramètre commençant par - peut être interprété comme un flag.
SQL string concatenation sur certains serveurs base de données qui exposent des tools de "schema query" : le nom de table est interpolé dans la requête sans bindings paramétrés.
Traiter toute entrée venant d'un appel tool comme non-fiable, exactement comme on traite une entrée utilisateur web. La présence d'un agent LLM entre la source et le serveur ne change rien : l'agent est un canal, pas un filtre.
Pattern 04Secrets en clair dans les configurations
Le quatrième pattern concerne la gestion des secrets côté serveur MCP. Les serveurs qui appellent des API tierces (GitHub, Slack, Google Drive, services cloud) ont besoin de tokens d'accès. Le modèle standard dans l'écosystème actuel est de passer ces tokens via des variables d'environnement définies dans le fichier de configuration du client.
Plusieurs problèmes observés :
- Les fichiers de configuration MCP (par exemple
claude_desktop_config.json) contiennent les tokens en clair et sont stockés dans le home utilisateur sans permissions restrictives par défaut sur certaines plateformes. - Les serveurs eux-mêmes loggent souvent leur configuration au démarrage, en mode debug, avec les tokens visibles dans les fichiers de log.
- Plusieurs serveurs exposent un tool de type
get_configoudebug_infoqui retourne la configuration courante à l'agent, faisant ainsi entrer le token dans le contexte de l'agent — où il peut être exfiltré via prompt injection indirecte (cf. Pattern 05).
Le pattern défensif : les tokens d'accès doivent venir d'un keychain OS (macOS Keychain, Windows Credential Manager, libsecret) ou d'un secret manager dédié, pas d'un fichier de configuration en clair. Les serveurs ne doivent jamais exposer de tool qui retourne leur configuration ou un secret au contexte agent, même en mode debug.
Pattern 05Prompt injection indirecte via les sorties de tools
Le cinquième pattern est le plus subtil et probablement le plus impactant à long terme. Quand un agent appelle un tool, la sortie est insérée dans son contexte et influence ses décisions suivantes. Si cette sortie contient du texte adversarial — instructions cachées, contenu Markdown trompeur, séquences imitant un message système — l'agent peut être détourné de son objectif initial.
Les surfaces où ce pattern se matérialise sur les serveurs audités :
- Serveur
fetch: récupère arbitrairement le contenu HTML d'une URL fournie par l'agent. Le contenu est inséré tel quel dans le contexte. Une page web contrôlée par un tiers peut contenir, dans son corps ou ses commentaires HTML, des instructions qui réorientent l'agent. - Serveur
brave-searchet autres search : les résultats de recherche contiennent les méta-descriptions des sites résultats, lesquelles sont contrôlées par les propriétaires des sites en question. - Serveur
filesystem: tout fichier lu peut contenir des instructions. Cas particulièrement piégeux : les fichiers de log, README, ou notes textuelles parcourues par l'agent dans un workflow légitime. - Serveur
github: descriptions d'issues, contenu de PR, commentaires — tout ce qu'un contributeur externe peut soumettre.
Aucune mitigation parfaite côté serveur MCP. La défense est à plusieurs niveaux :
- Marquage syntaxique des sorties de tools : encapsuler la sortie dans un délimiteur typé pour signaler clairement à l'agent que c'est du contenu non-fiable.
- Sanitization basique : retirer les séquences qui imitent des balises de prompt système connues, normaliser les caractères de contrôle.
- Guardrails côté agent : entraînement explicite à ne pas suivre d'instructions venues d'une sortie tool comme s'il s'agissait d'une consigne utilisateur. C'est le travail que fait Anthropic avec les Constitutional Classifiers et le Cyber Verification Program.
- Audit log côté client : conservation des sorties tools pour permettre une analyse post-incident quand un agent dévie.
Recommandations pratiques pour les équipes qui intègrent MCP
Une checklist défensive pour les équipes qui déploient MCP en production :
- Inventaire : listez tous les serveurs MCP utilisés, leur source, leur version, et la dernière revue de code effectuée par votre équipe (et pas seulement par la communauté).
- Isolation processus : exécutez chaque serveur MCP dans un container ou un sandbox avec les permissions filesystem et réseau strictement nécessaires.
- Pas de HTTP en LAN : interdisez l'exposition de serveurs MCP sur des interfaces réseau non-restrictives. stdio ou socket Unix avec permissions explicites uniquement.
- Secrets externalisés : tous les tokens d'accès en keychain OS ou secret manager, jamais dans les fichiers de configuration MCP en clair.
- Scope minimal : pour les serveurs filesystem, ne donnez accès qu'aux dossiers strictement nécessaires. Pour les serveurs base de données, utilisez un utilisateur SQL avec privilèges minimaux.
- Logging des appels tools : conservez un journal des appels tools, paramètres, et sorties pour audit post-incident. C'est le seul moyen de remonter une chaîne d'injection indirecte après coup.
- Revue régulière : les serveurs MCP évoluent vite. Refaites une revue de code à chaque mise à jour majeure, pas seulement à l'intégration initiale.
Conclusion
MCP est une infrastructure puissante qui va continuer à se diffuser dans les workflows enterprise en 2026 et au-delà. Les patterns décrits ici ne sont pas des failles du protocole — ce sont des erreurs récurrentes d'implémentation et de modèle de confiance qui se répètent parce que l'écosystème est jeune et que la culture de revue sécurité pour les fournisseurs de capacités d'agents n'est pas encore mature.
La trajectoire défensive utile est claire : traiter chaque serveur MCP comme un composant non-fiable de la chaîne, avec son propre modèle de menaces, son propre périmètre de confiance, et son propre processus de revue. La présence d'un agent LLM entre l'utilisateur et le serveur ne neutralise aucune des classes de vulnérabilité classiques — elle en introduit de nouvelles, notamment via la prompt injection indirecte (Pattern 05) qui n'a pas d'équivalent direct dans le monde des API REST.
Pour les équipes qui veulent aller plus loin, deux directions productives : (1) l'instrumentation continue des appels tools pour détection d'anomalie comportementale, et (2) l'évaluation des classifiers de leur fournisseur LLM face à des entrées adversariales injectées via tools — ce que les programmes de bug bounty modèles, dont le Model Safety Bug Bounty Program d'Anthropic, formalisent depuis 2024.
Khaled Abdelli — Neurodopa
Mai 2026, Chantepie.
Pour discuter d'un audit MCP / AI red team sur votre périmètre : business@neurodopa.fr