# Un serveur MCP mal isolé exposait des outils d’admin à tout agent connecté

> Un serveur MCP configuré sans distinction de périmètre laissait n'importe quel agent connecté appeler des outils réservés aux administrateurs. Diagnostic et correctif par des scopes explicites.

- Auteur : Clément Hadrot
- Publié le : 2025-03-07
- Mis à jour le : 2025-03-07
- Catégorie : Sécurité
- URL : https://wpmoderne.dev.wordpress-developpement.fr/securite/serveur-mcp-mal-isole-outils-admin-exposes/

## L’essentiel

- Un seul serveur MCP servait tous les usages sans distinction
- Un agent marketing pouvait appeler des outils de gestion des utilisateurs
- Le correctif a introduit des scopes nommés par cas d'usage

**Symptôme.** Un client gérant une plateforme de mise en relation entre freelances et entreprises avait mis en place un serveur MCP unique pour l'ensemble de ses automatisations WordPress : un agent chargé de générer des descriptions de missions à partir de briefs clients, un autre chargé de relancer les profils inactifs par email, et un troisième, plus expérimental, chargé de tester des scénarios de matching automatique entre profils. Les trois agents se connectaient au même serveur MCP, avec les mêmes identifiants d'authentification partagés entre eux.

Un audit de routine, mené après l'ajout du troisième agent expérimental, a consisté à faire l'inventaire de tous les outils que chaque agent pouvait effectivement appeler, plutôt que de se fier à ce que chacun était censé faire. Le résultat a montré que l'agent expérimental de matching, dont le rôle se limitait en théorie à lire des profils et proposer des correspondances, pouvait en réalité appeler quatorze outils différents, dont la création de comptes administrateurs et la modification des rôles utilisateurs, des fonctions sans aucun rapport avec sa tâche.

## Diagnostic : un serveur pensé pour la simplicité, pas pour l'isolation

La configuration du serveur MCP, développée initialement pour un seul usage puis étendue progressivement à mesure que de nouveaux agents étaient ajoutés, exposait l'ensemble de son catalogue d'outils à toute connexion authentifiée, sans distinction de scope. Le code d'enregistrement des outils ressemblait à ceci, une structure qui semblait raisonnable au départ, quand un seul agent était connecté :

```
const tousLesOutils = [
  genererDescriptionMission,
  relancerProfilInactif,
  listerProfils,
  proposerMatching,
  creerUtilisateur,
  modifierRoleUtilisateur,
  supprimerCompte,
  // ... 14 outils au total
];

server.on('connection', (agent) => {
  agent.outilsDisponibles = tousLesOutils; // aucune distinction
});
```

Cette approche fonctionnait tant qu'un seul agent, de confiance et bien testé, se connectait. Elle est devenue un risque réel dès l'ajout d'un deuxième puis d'un troisième agent, chacun avec un niveau de maturité et de supervision différent : l'agent expérimental de matching, encore en phase de test, avait accès aux mêmes outils sensibles que les agents de production, sans qu'aucune décision explicite n'ait jamais été prise en ce sens.

## Diagnostic approfondi : l'absence totale de traçabilité par agent

> L'essentiel à retenir : Un seul serveur MCP servait tous les usages sans distinction ; Un agent marketing pouvait appeler des outils de gestion des utilisateurs ; Le correctif a introduit des scopes nommés par cas d'usage

Le second problème, découvert en creusant plus loin, était que le serveur MCP journalisait les appels d'outils sans distinguer quel agent les avait effectués : tous les appels apparaissaient sous une même clé d'authentification partagée, celle du serveur MCP lui-même vis-à-vis de WordPress. En cas d'usage abusif d'un outil sensible, il aurait été impossible de déterminer lequel des trois agents en était la source sans reprendre manuellement l'historique complet des conversations de chacun, une tâche longue et peu fiable.

## Correctif : des scopes nommés par cas d'usage

La refonte a introduit la notion de scope explicite, un ensemble nommé d'outils associé à un identifiant d'agent unique, avec authentification distincte pour chaque agent plutôt qu'un secret partagé :

```
const scopes = {
  'agent-redaction-missions': [
    genererDescriptionMission,
  ],
  'agent-relance-profils': [
    listerProfils,
    relancerProfilInactif,
  ],
  'agent-matching-experimental': [
    listerProfils,
    proposerMatching,
  ],
};

server.on('connection', (agent) => {
  const scope = scopes[agent.identifiant];
  if (!scope) {
    agent.close();
    return;
  }
  agent.outilsDisponibles = scope;
});
```

Avec cette structure, l'agent expérimental de matching ne voit plus, dans son catalogue d'outils, ni `creerUtilisateur`, ni `modifierRoleUtilisateur`, ni aucun des douze autres outils qui ne concernaient pas sa tâche. Chaque agent dispose de son propre identifiant, ce qui permet également de tracer précisément, dans les journaux, quel agent a appelé quel outil et à quel moment.

## Vérifier l'isolation après correctif

La vérification de ce type de correctif ne peut pas se contenter de relire la configuration : il faut tester activement qu'un agent restreint ne peut effectivement plus appeler un outil hors de son scope, en simulant l'appel directement :

```
curl -X POST https://exemple.fr/mcp/agent-matching-experimental/call \
  -H "Authorization: Bearer TOKEN_AGENT_MATCHING" \
  -d '{"tool": "creerUtilisateur", "params": {}}'
# Doit renvoyer une erreur de type outil_non_autorise, pas une exécution
```

Cette vérification a été ajoutée à la suite de tests automatisés du projet, exécutée à chaque modification du serveur MCP, pour garantir que l'ajout futur d'un nouvel outil au catalogue global ne se retrouve pas accessible par erreur à tous les agents existants sans décision explicite.

## Ce qu'un serveur MCP multi-agents doit prévoir dès sa conception

- Un identifiant d'authentification distinct par agent, jamais un secret partagé entre plusieurs usages.
- Un catalogue d'outils défini par scope nommé, jamais exposé intégralement par défaut à toute connexion.
- Un rejet explicite de la connexion si l'agent ne correspond à aucun scope déclaré, plutôt qu'un repli silencieux vers un accès large.
- Une journalisation qui distingue chaque agent individuellement, pour permettre une investigation rapide en cas d'usage anormal.

> Un serveur MCP qui grandit au fil des besoins hérite souvent d'une architecture pensée pour un seul agent de confiance. Le danger apparaît précisément le jour où un deuxième agent, moins éprouvé, vient s'y connecter sans qu'on ait revu les fondations.

## Ce que révèle ce cas

Aucun dommage réel n'a été constaté sur ce site : l'audit a précédé toute exploitation malveillante ou toute erreur de l'agent lui-même. Le cas reste néanmoins instructif parce qu'il illustre un piège de conception fréquent avec les serveurs MCP développés en interne, souvent construits rapidement pour un premier besoin puis étendus sans revue de sécurité à chaque nouvel agent ajouté. L'isolation par scope n'est pas une fonctionnalité optionnelle à ajouter plus tard : elle doit faire partie de la conception initiale du serveur, dès le moment où l'on envisage qu'un deuxième usage viendra un jour s'y greffer.
