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

Des instances de serveur MCP réutilisées fuitent d'un client à l'autre

Une faille de conception du SDK TypeScript officiel du Model Context Protocol permettait qu'un serveur ou un transport partagé achemine les résultats d'outils, notifications et requêtes de sampling d'un client vers un autre. Corrigé en 1.26.0.

2026-07-15 // 6 min affects: mcp-servers, modelcontextprotocol-sdk, llm-agents, multi-tenant-ai-platforms

De quoi s’agit-il ?

Le 4 février 2026, un mainteneur du SDK TypeScript officiel du Model Context Protocol (MCP) a publié un avis de sécurité pour une fuite de données entre clients dans @modelcontextprotocol/sdk. Ce n’est ni un payload ni une injection : c’est un bug de concurrence dans la manière dont le SDK achemine les réponses. Lorsqu’une seule instance de serveur ou de transport HTTP est partagée entre plusieurs clients connectés, un client peut recevoir des données destinées à un autre — résultats d’outils, contenus de ressources, notifications de progression, et requêtes de sampling ou d’elicitation peuvent toutes être livrées à la mauvaise connexion.

L’avis concerne les versions 1.10.0 à 1.25.3 du SDK et est corrigé en 1.26.0. Il est noté 7,1 (élevé) et classé comme condition de concurrence (CWE-362). Nous le signalons car le schéma vulnérable — un seul objet serveur traitant toutes les requêtes — correspond exactement à la façon dont beaucoup de développeurs câblent un serveur MCP pour la première fois, et parce que MCP est désormais le tissu conjonctif entre les agents LLM et les outils d’entreprise. Cet article est une synthèse défensive ; il ne reproduit aucun exploit, car aucun n’est nécessaire pour comprendre la défaillance.

Comment ça marche

L’avis décrit deux problèmes distincts mais liés, et un déploiement peut souffrir de l’un, de l’autre, ou des deux.

Le premier est la réutilisation du transport. Le transport HTTP en streaming du SDK conserve une table interne associant un identifiant de requête JSON-RPC au flux HTTP en attente de cette réponse. Les clients MCP génèrent leurs identifiants avec un compteur qui commence à zéro et s’incrémente. Deux clients qui se connectent indépendamment envoient donc tous deux l’identifiant 0, puis 1, puis 2. Si une seule instance de transport les sert, l’entrée du second client écrase celle du premier dans la table, et la réponse est écrite sur le mauvais flux. Tous les types de requêtes sont exposés — appels d’outils, lectures de ressources, récupérations de prompts — et aucune fonctionnalité initiée par le serveur n’est requise pour déclencher le problème.

Le second est la réutilisation du serveur (protocole). Lorsqu’un seul objet serveur est connecté à plusieurs transports, un par client, la couche protocole conserve une unique référence vers « le transport courant », et chaque nouvelle connexion l’écrase silencieusement. Les réponses finales sont généralement acheminées correctement, car la référence est capturée à l’arrivée de la requête, mais tout ce qui est envoyé pendant le traitement — notifications de progression, appels de sampling vers le modèle, prompts d’elicitation ou notifications spontanées du serveur — transite par la référence partagée et peut atterrir sur la connexion d’un autre client.

La cause commune est un état mutable partagé sans isolation par client, qui ne se manifeste que sous concurrence. La configuration la plus exposée est le mode stateless, où un serveur est instancié sans générateur de session et réutilisé entre les requêtes pour économiser des allocations — un raccourci de performance courant qui devient une rupture de frontière de données dès que deux utilisateurs sont actifs simultanément.

Pourquoi c’est important

Les serveurs MCP se placent de plus en plus devant des données réelles : magasins de fichiers, bases de données, systèmes de tickets, API internes et les identifiants que ces outils transportent. Une réponse mal acheminée n’est donc pas un défaut cosmétique — elle peut remettre à un locataire les résultats de requête, contenus de documents ou messages d’erreur d’un autre locataire. Dans un déploiement multi-utilisateurs, cela franchit une frontière de sécurité que l’exploitant supposait garantie par le framework.

L’exposition est large précisément parce que le bug réside dans le SDK de référence plutôt que dans un seul produit. Tout serveur MCP hébergé bâti sur les versions affectées et servant des clients concurrents peut être touché, et le déclencheur est la charge ordinaire, pas une attaque forgée. La faible probabilité d’exploitation mesurée reflète le fait qu’un attaquant ne peut pas choisir de façon fiable les données qu’il reçoit — mais une fuite accidentelle entre locataires sous trafic normal constitue en soi un problème de confidentialité et de conformité, indépendamment de toute tentative d’exploitation active.

Défenses

Mettez à jour le SDK vers la version 1.26.0 ou ultérieure. Le correctif ne masque pas la course : il transforme le mauvais acheminement silencieux en erreurs bruyantes et immédiates — connecter un protocole déjà connecté lève désormais une exception, et un transport stateless refuse de traiter plus d’une requête — de sorte que les mauvaises configurations échouent en mode fermé plutôt que de fuiter.

Si vous ne pouvez pas mettre à jour immédiatement, créez une nouvelle instance de serveur et de transport par connexion. En mode stateless, instanciez les deux à l’intérieur du gestionnaire de requête et détruisez-les ensuite ; en mode stateful, associez un nouveau serveur et un nouveau transport à l’identifiant de session et stockez-les par session. Ne partagez jamais un seul objet serveur entre sessions si vos outils envoient des notifications de progression, du sampling ou de l’elicitation en cours d’exécution.

Auditez la topologie de votre déploiement. Posez précisément la question : un seul objet serveur ou transport est-il réutilisé entre les requêtes, et deux clients peuvent-ils être traités simultanément ? Si oui, vous correspondez au schéma vulnérable quelle que soit la version du SDK, et vous devriez confirmer la présence des garde-fous d’exécution.

Traitez l’isolation entre locataires comme quelque chose que l’on vérifie, pas que l’on suppose. Ajoutez des tests d’intégration qui pilotent deux clients concurrents à travers le même serveur et vérifient que chacun ne reçoit que ses propres réponses, ainsi qu’une télémétrie capable de détecter une réponse arrivant sur une session inattendue. La leçon générale survit à cette seule référence : dans l’infrastructure d’agents, l’état par client doit être par client par construction, et « réutiliser l’objet pour aller plus vite » est une décision de frontière de données, pas seulement de performance.

Statut

ÉlémentDétail
Composant@modelcontextprotocol/sdk (SDK TypeScript MCP)
AvisGHSA-345p-7cg4-v4c7 / CVE-2026-25536, publié le 4 février 2026
Affecté1.10.0 à 1.25.3
Corrigé1.26.0
ClasseCondition de concurrence (CWE-362), mauvais acheminement des réponses entre clients
Sévérité7,1 (élevé) ; impact confidentialité élevé, probabilité d’exploitation faible
ExploitationAucune preuve publique d’exploitation

Sources