Retour
Secrets & données exposées12 sept. 2026 · 5 min de lecture

21 000 serveurs MCP exposés sur Internet : pourquoi l'authentification est « optionnelle »

par detektd team

Câbles réseau orange débranchés qui pendent devant une baie de brassage sombre
Photo : rawpixel · CC0 · rawpixel

Le Model Context Protocol (MCP) est devenu en un an le standard de fait pour brancher des outils à un assistant IA : une base de données, un dépôt Git, un CRM, un shell. Un serveur MCP expose des outils ; un client (Claude, Cursor, un agent maison) les découvre et les appelle. Le protocole a été pensé d'abord pour tourner en local. Il tourne désormais, massivement, sur Internet.

Fin avril 2026, Censys a identifié 12 520 services MCP accessibles depuis Internet, répartis sur 8 758 adresses IP ; début mai, le compteur dépassait 21 000. Le 31 juillet, une étude publiée sur arXiv, « Exposed by Design », a pris la mesure de ce parc de façon dynamique : 640 serveurs de production confirmés, 414 audités, 68 vulnérabilités signalables. Et surtout, 91,8 % des serveurs audités ne mettaient en place aucune authentification OAuth.

0,0%

des serveurs MCP de production audités n'avaient aucune authentification OAuth (arXiv 2608.00150, juillet 2026)

Comment fonctionne MCP

Sous le capot, MCP est du JSON-RPC 2.0. Une session commence par un échange initialize, où client et serveur annoncent leur version de protocole et leurs capacités. Le client appelle ensuite tools/list pour obtenir la liste des outils, chacun décrit par un nom, une description en langage naturel et un schéma JSON de ses arguments. Puis tools/call pour en exécuter un. Le serveur peut aussi exposer des « resources » (des données adressables) et des « prompts » (des modèles d'interaction).

Un outil tel que le décrit tools/list
{
  "name": "query_customers",
  "description": "Run a read query against the customers table",
  "inputSchema": {
    "type": "object",
    "properties": { "sql": { "type": "string" } },
    "required": ["sql"]
  }
}

Le protocole définit deux transports. Le premier, stdio, fait tourner le serveur comme un sous-processus du client : aucun port réseau, aucune exposition possible, et la spécification demande aux clients de le privilégier. Le second, Streamable HTTP, fait du serveur un service HTTP indépendant, avec un point d'accès unique qui accepte POST et GET et peut répondre en flux (Server-Sent Events). Il a remplacé en mars 2025 l'ancien transport HTTP+SSE de la version 2024-11-05, encore présent sur beaucoup de déploiements.

« OPTIONAL »

La spécification d'autorisation de MCP s'ouvre sur une phrase qui explique une bonne partie des chiffres : l'autorisation est OPTIONNELLE, en majuscules, au sens des RFC. Quand elle est implémentée, elle est solide : OAuth 2.1 avec PKCE obligatoire, découverte du serveur d'autorisation via les métadonnées de ressource protégée (RFC 9728), jetons liés à leur destinataire par les indicateurs de ressource (RFC 8707), et interdiction explicite de relayer tel quel un jeton reçu vers une autre API. Mais rien n'oblige à l'implémenter.

Ce choix a du sens pour stdio, où le serveur hérite des droits de l'utilisateur local. Il en a beaucoup moins pour un service HTTP. La section sécurité du transport HTTP le reconnaît d'ailleurs : les serveurs DOIVENT valider l'en-tête Origin de chaque connexion pour empêcher les attaques par rebinding DNS, DEVRAIENT n'écouter que sur 127.0.0.1 quand ils tournent en local, et DEVRAIENT authentifier toutes les connexions.

Comment un serveur local finit sur Internet

Le scénario type est banal. Un serveur MCP démarre en local, en stdio. Pour le partager avec l'équipe, on passe au transport HTTP et on le met dans un conteneur. Puis on le déploie sur une instance cloud. À aucune étape on n'a décidé de l'exposer publiquement ; à chaque étape, c'est devenu un peu plus vrai. Censys note que 61,5 % des services trouvés répondaient directement sur une adresse IP nue, sans nom de domaine, le signe de déploiements rapides plutôt que de services conçus pour être publics.

Docker ajoute un piège classique. Publier un port avec -p 8080:8080 l'ouvre sur toutes les interfaces de la machine, et Docker écrit ses propres règles iptables, qui passent avant celles d'un pare-feu comme ufw. Un administrateur qui pense avoir fermé le port dans ufw peut donc l'avoir laissé ouvert au monde.

Publier un port uniquement en local
# exposed on every interface, and past ufw
docker run -p 8080:8080 my-mcp-server

# reachable from this machine only
docker run -p 127.0.0.1:8080:8080 my-mcp-server
Serveur en stdio, local
Passage en HTTP, conteneurisé
Déployé sur une IP publique
Outils appelables par n'importe qui

Ce qui est exposé

Les chiffres de Censys, obtenus sans jamais appeler un seul outil (uniquement à partir de ce que les serveurs annoncent pendant l'initialisation), donnent la mesure du risque. 88,3 % des serveurs exposent au moins un outil. Environ 90 annoncent des outils d'exécution de commandes, et 1 056 des interfaces de requête directe vers des bases SQL, NoSQL ou vectorielles. Les catégories les plus représentées sont les données (bases, bases de connaissances) et l'infrastructure (contrôle de systèmes, gestion cloud).

L'étude arXiv est allée plus loin, avec un cadre de test dédié couvrant dix classes de vulnérabilités propres à MCP. Parmi les 68 failles signalées : injections SQL à travers les arguments d'outils, SSRF vers les services de métadonnées cloud, injection dans des modèles de prompts, traversée de chemin. Un détail rend le problème difficile à suivre : 41,6 % des serveurs confirmés avaient disparu d'une campagne de mesure à l'autre, en moins de trois jours. Des serveurs éphémères, lancés pour un essai et parfois oubliés.

L'authentification ne suffit pas

Censys le rappelle : un serveur MCP authentifié reste exposé à l'injection de prompt, puisque c'est un client légitime, l'agent, qui l'appelle avec des arguments dérivés de contenus non fiables. L'authentification ferme la porte aux inconnus ; elle ne protège pas contre un agent manipulé.

Déployer un serveur MCP proprement

  1. Rester en stdio tant que le serveur n'a pas besoin d'être partagé. Aucun port, aucune surface.
  2. En HTTP local : écouter sur 127.0.0.1 et valider l'en-tête Origin, comme l'exige la spécification, sans quoi une page web visitée par le développeur peut parler au serveur via un rebinding DNS.
  3. En HTTP distant : implémenter l'autorisation OAuth 2.1 de la spécification, ou au minimum placer le serveur derrière une passerelle authentifiée. Jamais d'IP publique nue.
  4. Réduire chaque outil au strict nécessaire : un utilisateur de base de données en lecture seule plutôt qu'un outil SQL libre, des chemins de fichiers restreints à un répertoire, aucun accès aux métadonnées cloud.
  5. Tenir un inventaire : un serveur lancé « pour tester » et jamais arrêté est exactement celui qui finit dans les statistiques.

Quand detektd trouve un point d'accès MCP sur le domaine scanné, il procède comme Censys : il lit la liste des outils annoncés, sans jamais en appeler un seul. La sévérité dépend de ce qu'ils permettent : un serveur qui expose sans authentification un shell, un accès aux fichiers, des requêtes SQL ou des appels HTTP arbitraires est classé comme élevé.

21 000 serveurs MCP exposés sur Internet : pourquoi l'authentification est « optionnelle » | detektd