Contexte et configuration

Le test repose sur un compte ChatGPT disposant de deux connecteurs actifs pointant vers le même serveur MCP. Le connecteur A est un connecteur personnalisé ajouté en mode développeur, tandis que le connecteur B provient de l’annuaire d’applications publié. Chaque connecteur possède son propre client OAuth, ce qui fait que le serveur MCP voit deux identités d’application distinctes pour le même utilisateur.

Mécanisme de l’appel d’outil et du code de confirmation

Lors d’une conversation où les deux connecteurs sont activés, l’utilisateur demande une action nécessitant une confirmation. Le modèle invoque d’abord l’outil de confirmation via le connecteur A. Le widget MCP Apps du connecteur A affiche le formulaire de confirmation, l’utilisateur valide, et le widget renvoie un code de confirmation à usage unique dans le fil de discussion via ui/message. Immédiatement après, le modèle effectue un appel de suivi en réutilisant ce code, mais cette fois-ci via le connecteur B. Le serveur MCP rejette l’appel parce que le code est lié au client OAuth du connecteur A, alors que la requête provient du client du connecteur B.

Analyse de la faille de passage de données

Le problème réside dans le fait que le modèle ne signale pas à l’utilisateur le basculement du flux d’un connecteur à l’autre. Le code de confirmation, généré et validé dans le contexte du connecteur A, est transmis sans contrôle supplémentaire à un autre contexte d’application. Cette « silence switch » viole le principe de séparation des privilèges entre deux applications OAuth distinctes : chaque client doit recevoir uniquement les données qu’il a explicitement autorisées. En pratique, le serveur MCP détecte l’incohérence et refuse l’appel, mais l’échec se produit après que le code a déjà été exposé dans le fil de discussion, créant ainsi une surface d’exposition inutile.

Implications et mesures d’atténuation

Cette situation montre que les flux de travail multi‑connecteurs peuvent être exploités pour transférer indirectement des jetons ou des codes sensibles entre applications sans consentement explicite. Les risques incluent la compromission de données d’authentification, la possibilité d’escalade de privilèges si un attaquant contrôle l’un des connecteurs, et la perte de confiance de l’utilisateur. Pour atténuer le problème, il est recommandé de :

1. Implémenter une validation stricte du contexte d’appel : le serveur doit rejeter immédiatement tout code reçu d’un client OAuth différent, sans attendre la phase de traitement du modèle.

2. Notifier l’utilisateur : chaque changement de connecteur doit générer un message d’avertissement explicite dans la conversation.

3. Restreindre les appels de suivi : limiter la capacité du modèle à réutiliser des valeurs de confirmation à moins qu’elles ne proviennent du même connecteur d’origine.

4. Auditer les logs : consigner les tentatives de basculement afin de détecter d’éventuels abus.