Accueil / Articles

Chaque serveur MCP représente un secret de plus que votre agent peut divulguer.

Chaque serveur MCP représente un secret actif supplémentaire et élargit la portée des entrées malveillantes. Auditez les plages d’accès des tokens et appliquez quatre correctifs pour réduire la portée de l’attaque.

Éditeur : REACTAPP.TOP4 min de lecture950 mots

Sources: Every MCP Server You Add Gives Your Agent Another Credential

Cela commence innocemment. GitHub est connecté le lundi, Slack le mardi, puis Postgres, puis Notion, puis un serveur de facturation interne que quelqu’un a écrit en une après-midi sans jamais le documenter. Chaque ajout rend l’agent plus performant. Chacun ajoute également une clé à la chaîne qu’il porte avec lui.

Les problèmes apparaissent généralement par hasard, lorsque quelqu’un débogue quelque chose de sans rapport et ouvre le fichier de configuration. Six serveurs, six secrets actifs, tous en texte brut dans un répertoire personnel, sans date d’expiration et sans propriétaire. À ce stade, MCP cesse de ressembler à un outil pratique pour devenir plutôt une source de risques.

Les calculs

Après quelques mois d’enthousiasme, une configuration typique ressemble à ceci :

{
  "mcpServers": {
    "gh": { "cmd": "gh-mcp",  "env": { "GH_TOKEN": "ghp_live_9f2a" } },
    "db": { "cmd": "pg-mcp",  "env": { "PG_URL": "postgres://app:hunter2@prod/main" } },
    "sl": { "cmd": "slk-mcp", "env": { "SLACK_TOKEN": "xoxb-live-771" } }
  }
}

Trois serveurs, trois secrets, un fichier et pas de rotation. Vous pouvez vérifier votre propre machine en quelques secondes en recherchant dans les dossiers de configuration habituels des chaînes ressemblant à des jetons.

grep -rIl "ghp_\|xoxb-\|sk-" ~/.config ~/.claude ~/Library 2>/dev/null | wc -l

Les personnes qui s’en occupent trouvent souvent plus que ce à quoi elles s’attendaient. Un total de onze alors que l’on pensait à trois n’est pas inhabituel.

La partie qui fait vraiment mal

Les identifiants stockés sur le disque représentent la moitié moins grave du problème. La partie plus sérieuse, c’est que chacun de ces identifiants dépend désormais d’une seule personne décisionnaire, et cette personne lit du texte sur Internet.

                    one agent loop
                          |
      +---------+---------+---------+---------+
      |         |         |         |         |
    github    slack   postgres   notion    billing
   (14 scp)  (9 scp)  (rw all)  (rw ws)   (rw all)
      |         |         |         |         |
      +---------+---------+---------+---------+
                          |
                 one poisoned input

Un commentaire, une page Notion ou une ligne dans un tableau peuvent chacun suggérer une action, et l’agent dispose de toutes les informations nécessaires pour la mettre en œuvre. Il s’agit du problème du délégué confus sous un autre jour. L’agent n’est pas compromis ; il est simplement utile, et il ne parvient pas à distinguer vos instructions des textes qui leur ressemblent seulement.

Évaluer l’écart

Un exercice utile consiste à enregistrer chaque appel à l’outil pendant deux semaines, puis à comparer ce à quoi chaque token est autorisé de faire avec ce qu’il a réellement fait. Un résultat d’un tel audit :

| Service  |  Granted Scopes |         Scopes Used | Utilization |
| -------- | --------------: | ------------------: | ----------: |
| GitHub   |              14 |                   3 |       21.4% |
| Slack    |               9 |                   2 |       22.2% |
| Postgres |         Full RW | 1 table, reads only |     Minimal |
| Notion   | Whole workspace |             2 pages |     Minimal |

Environ quatre cinquièmes des accès accordés n’ont pas été utilisés. Ce manque n’est pas une question de commodité : c’est un risque supplémentaire que l’on assume sans en tirer aucun avantage.

Solutions, classées par efficacité

Un jeton par serveur, adapté à sa fonction réelle. Des jetons partagés entraînent des responsabilités partagées. Lorsqu’un problème survient, le journal d’audit doit pointer vers un serveur et non vers une personne.

Par défaut, tout élément contenant des données doit être en mode lecture seule. Deux lignes de SQL, un rôle dédié ainsi que des droits de lecture limités aux tables que l’agent consulte réellement suffisent à transformer le pire scénario – la perte d’une table – en un simple fuitement de requête.

create role agent login password 'rotate_me';
grant usage on schema public to agent;
grant select on orders, users to agent;

Des jetons à durée de vie courte en remplacement de ceux permanents. Faites en sorte qu’un coffre-fort émette des identifiants sur demande, avec une durée de validité mesurée en minutes. Un secret volé mardi matin n’a plus aucune valeur mardi après-midi.

async function tok(srv) {
  const r = await fetch(`${VAULT}/issue/${srv}`, { method: "POST" });
  const { token, ttl } = await r.json();
  return { token, exp: Date.now() + ttl * 1000 };
}

Enregistrer les appels, et pas seulement les conversations. Un petit module d’enveloppement qui enregistre le serveur, les arguments ainsi qu’une date et heure pour chaque fonction de l’outil ne nécessite que quelques lignes de code. Dans l’audit mentionné ci-dessus, cela a révélé qu’un serveur appelait une extrémité de réseau à laquelle personne ne lui avait demandé de s’adresser.

function wrap(name, fn) {
  return async (args) => {
    log({ srv: name, args, at: Date.now() });
    return fn(args);
  };
}

Une règle à adopter

Avant d’intégrer un serveur, imaginez-le comme un élément hostile et demandez-vous ce à quoi il pourrait accéder sans aucune aide. Lorsque la réponse honnête est dérangeante, restreignez les droits associés ou éliminez ce serveur. Ne promettez pas de le corriger plus tard, car ce moment arrive rarement, surtout un vendredi.

Tout cela n’est pas une critique envers MCP. Il a résolu le problème d’intégration qui faisait que les agents semblaient être de simples jouets. Le point clé est que chaque serveur ajouté introduit également des identifiants, et ces derniers méritent les mêmes précautions que n’importe quelle autre clé utilisée en production.

Lectures complémentaires

  • Un flux de travail d’agent LLM local construit à partir de dossiers et de fichiers Markdown — Créez un pipeline d’agent local à étapes multiples avec des accès contrôlés, où chaque étape correspond à un dossier, les prompts sont des fichiers Markdown modifiables, et un humain examine les résultats avant l’étape coûteuse.
  • Un server MCP personnel permettant à Claude de rechercher vos runbooks d’équipe — Indexez les runbooks et les analyses post-incident en Markdown dans ChromaDB, exposez une recherche sémantique via un server MCP, et permettez à Claude de trouver les procédures d’incident en quelques secondes.