Aller au contenu

MCP

Auditer Claude Code et les serveurs MCP en environnement auto-hébergé

Par Olivares AI 7 min de lecture

Une équipe plateforme déploie Claude Code auprès d’une douzaine d’ingénieurs. Pour le rendre utile, elle le raccorde à quelques serveurs MCP : un qui lit le monorepo, un qui interroge un réplica de reporting, un qui ouvre des tickets. En une semaine, un agent lit du code source, touche une base de données et appelle des outils internes — et personne ne sait répondre à la question qu’un auditeur finira par poser : quel agent a fait quoi, sur quelle ressource, et pouvez-vous prouver que rien n’a été altéré ensuite ?

Ce manque n’a rien d’hypothétique. Une recherche indépendante du secteur (CSA/Token, n=418) a établi qu’environ 82 % des organisations ont des agents IA en fonctionnement dont elles ignorent l’existence, alors que seules 21 % environ en tiennent un inventaire en temps réel. Claude Code et MCP sont précisément le genre de capacité qui s’installe vite et prend de l’avance sur la traçabilité de l’audit. La bonne nouvelle : une piste défendable est réalisable entièrement à l’intérieur de votre propre périmètre, sans qu’aucune charge utile ni aucun secret n’en sorte.

Pourquoi le montage évident échoue à l’audit

Le premier déploiement habituel partage un seul identifiant. Chaque instance de Claude Code s’authentifie auprès de la couche MCP et des bases de données en aval sous le même compte de service — mcp-runner, ci-bot, quelque chose de générique. Cela fonctionne, et cela détruit silencieusement l’attribution.

Quand dix agents agissent comme un seul principal, le journal d’audit de la base de données montre dix écritures depuis mcp-runner, et rien de plus. Vous ne pouvez pas dire quelle session d’ingénieur a émis l’UPDATE, s’il provenait d’une invite Claude Code interactive ou d’une tâche sans surveillance, ni quel outil MCP figurait dans le chemin. Une recherche indépendante (Optro) chiffre à environ 28 % la proportion d’organisations capables de remonter d’une action d’agent jusqu’à une personne. Un compte de service partagé est l’une des raisons structurelles de l’effondrement de l’attribution : le journal d’audit peut montrer ce qui s’est passé, mais jamais quel agent l’a fait.

Le second échec porte sur l’intégrité. Même les équipes qui consignent chaque action écrivent en général dans un stockage modifiable. Si les journaux résident dans le même système qu’un attaquant (ou un agent bogué) peut atteindre, « nous avons des journaux » n’équivaut pas à « nous avons des preuves ». Un auditeur distingue nettement les deux.

L’identité par agent est le fondement

Tout ce qui suit dépend de l’attribution : commencez donc par régler l’identité. Au lieu d’un jeton partagé unique, émettez une identité distincte et à durée de vie courte par agent — idéalement par session. L’identité accompagne la requête jusque dans le serveur MCP et dans toute ressource que l’agent atteint : le principal consigné au niveau de la base de données est ainsi l’agent, et non un exécuteur générique.

C’est ce qui donne tout son sens au moindre privilège. Un agent de reporting peut être restreint en lecture seule sur le réplica de reporting ; un agent de release n’obtient l’écriture que sur les artefacts qu’il possède. Dès lors, une seule écriture observée hors de cette enveloppe devient un signal précis et attribuable, au lieu d’un bruit noyé dans un compte partagé. Exprimée sous forme de politique, l’intention est sans détour :

agent "reporting-assistant" {
  # Session Claude Code via le serveur MCP de reporting
  resource "prod-postgres/reporting_replica" {
    access     = "read"      # SELECT only
    deny       = ["write", "ddl"]
  }
  resource "s3://billing-exports" {
    access = "read"
  }
  on_violation {
    action = "block_and_alert"   # refuse at access time, not just log
  }
}

L’essentiel n’est pas la syntaxe — c’est que la politique nomme l’agent, nomme la ressource et sépare la lecture de la lecture/écriture. Cette séparation est tout l’enjeu.

Traiter les annotations MCP comme des signaux non fiables

Les outils MCP peuvent se décrire eux-mêmes au moyen d’annotations telles que readOnlyHint et destructiveHint. Elles sont réellement utiles pour le triage — un outil qui se déclare destructeur mérite une politique plus stricte. Mais la spécification MCP est explicite : ce sont des indications, et les clients ne doivent pas s’en remettre à elles pour des décisions de sécurité. Elles proviennent du serveur, c’est-à-dire de ce que vous êtes précisément en train d’auditer. Un outil peut déclarer readOnlyHint: true et émettre malgré tout une écriture, que ce soit par un bogue, une mauvaise configuration ou une évasion délibérée.

La posture correcte est donc la corroboration, pas la confiance. Prenez l’annotation comme une affirmation, puis confrontez-la à la vérité terrain issue d’une couche que l’outil ne contrôle pas :

  • Les journaux d’audit de la base de données (par exemple pgAudit pour PostgreSQL) vous indiquent si un SELECT ou un UPDATE s’est réellement exécuté.
  • Les traces OpenTelemetry émises par le serveur MCP et les services en aval montrent le graphe d’appels et les opérations effectuées.
  • Les signaux noyau eBPF constituent le filet anti-évasion : un appel système d’écriture vers un fichier ou un socket est observable au niveau du noyau, quoi que l’outil ait pu prétendre en espace utilisateur.

Quand l’annotation dit lecture seule et que le noyau a vu une écriture, cette contradiction est le constat majeur — un outil readOnlyHint qui a écrit dans prod-postgres est exactement la dérive de moindre privilège qui justifie de réveiller quelqu’un. C’est dans l’écart entre ce que la politique a autorisé et ce que les collecteurs ont observé que réside le vrai risque.

Le registre qu’un auditeur acceptera

Une piste n’est une preuve que si elle est infalsifiable. Écrivez chaque événement dans un registre en ajout seul (append-only) et chaîné par hachage : chaque enregistrement contient le hachage du précédent, de sorte que toute modification ou suppression en aval rompt la chaîne et devient détectable. Chaque ligne attribue l’action à l’agent précis, nomme la ressource, consigne la lecture par rapport à la lecture/écriture et porte un niveau de confiance — attributed lorsque l’identité et le résultat sont tous deux corroborés, approximate lorsqu’il a fallu inférer quelque chose. La confiance est affichée honnêtement ; une correspondance approximative n’est jamais maquillée en correspondance prouvée.

ts=2026-06-08T09:14:02Z agent=reporting-assistant@s3f1 tool=sql-read     resource=prod-postgres/reporting_replica  op=R   outcome=allow   conf=attributed   prev=8a1c…
ts=2026-06-08T09:14:05Z agent=reporting-assistant@s3f1 tool=export-writer resource=s3://billing-exports          op=R   outcome=allow   conf=attributed   prev=2f90…
ts=2026-06-08T09:17:48Z agent=data-export-job@b22e     tool=sql-write     resource=prod-postgres/customers          op=RW  outcome=DENY    conf=attributed   prev=c7d3…  policy=read_only_violation

Cette troisième ligne est celle qui compte pour un auditeur : une tentative d’écriture sur une table pour laquelle l’agent n’avait aucun droit d’écriture, refusée au moment de l’accès, attribuée à un agent nommé et ancrée dans la chaîne. Parce que la politique est appliquée au moment où l’accès se produit — et pas simplement consignée après coup — le refus est un contrôle, pas une autopsie.

Deux propriétés supplémentaires font tenir la piste. Les vues privilégiées sont elles-mêmes auditées : consulter la carte des accès est consigné, si bien que « qui a vu quoi » a une réponse. Et l’export de preuves est infalsifiable — vous remettez à un auditeur une tranche signée de la chaîne qu’il peut vérifier de manière indépendante, plutôt qu’un CSV qu’il doit croire sur parole.

PropriétéCompte de service partagéIdentité par agent + registre chaîné par hachage
AttributionUn seul principal pour tous les agentsAction liée à l’agent/la session précis
Lecture vs écritureConfonduesDistinguées et vérifiées par la politique
IntégritéJournaux modifiablesAppend-only, la chaîne se rompt à la modification
Export prêt pour l’auditCSV pris sur paroleTranche signée, vérifiable de manière indépendante

Pourquoi l’auto-hébergement compte ici

Tout cela fonctionne sans que rien ne quitte votre réseau. Le collecteur observe — journaux, OpenTelemetry, eBPF comme filet de sécurité au niveau du noyau — au lieu de se placer sur le chemin de données de l’agent : s’il tombe en panne, il ne casse jamais l’agent ni la requête de production qui le sous-tend. Le registre stocke des relations d’accès, pas des charges utiles : il consigne que reporting-assistant a lu reporting_replica, pas les lignes qu’il a renvoyées. Les entrées susceptibles de contenir des secrets ou des données personnelles sont caviardées et soumises à une analyse de secrets avant toute écriture. Pour les parcs cloisonnés (air-gapped), soumis au RGPD ou contraints par la résidence des données, c’est là toute la différence entre une traçabilité d’audit que vous pouvez défendre et une que vous ne pouvez pas : rien de votre usage de Claude Code et de MCP ne « téléphone à la maison », parce que le système ne voit jamais les données en premier lieu.

Claude Code et MCP valent la peine d’être déployés. Il leur faut simplement une piste d’audit construite de la même manière que pour n’importe quelle autre automatisation privilégiée — l’identité d’abord, les résultats corroborés, les preuves ancrées. Pour voir comment la carte des accès et le registre infalsifiable s’articulent, le modèle de sécurité et la présentation du produit entrent davantage dans le détail de chacun.

Questions fréquentes

Puis-je me fier au readOnlyHint d'un outil MCP pour prouver qu'une action était en lecture seule ?

Non. La spécification MCP indique que les annotations d'outil telles que readOnlyHint et destructiveHint sont des indications et doivent être considérées comme non fiables, car elles proviennent du serveur et non d'une couche d'application des règles. Servez-vous-en pour le triage et pour signaler les contradictions, mais prouvez le résultat réel de lecture ou d'écriture à l'aide de la télémétrie ou de signaux au niveau du noyau (traces OpenTelemetry, journaux d'audit de la base de données, eBPF). Fiez-vous au résultat corroboré, pas à l'annotation.

Comment attribuer une action de Claude Code à un agent précis plutôt qu'à un compte de service partagé ?

Émettez une identité distincte et à durée de vie courte par agent ou par session, plutôt qu'un jeton partagé unique. Lorsque l'agent atteint une base de données ou un serveur MCP, cette identité accompagne la requête : le registre d'audit consigne ainsi quel agent a fait quoi. Un compte de service partagé fait fusionner tous les agents en un seul principal et rend impossible, après coup, le moindre privilège par agent et l'attribution infalsifiable.

Découvrez ce que vos agents peuvent atteindre

Olivares AI est la plateforme ouverte et auto-hébergée pour votre parc informatique d'IA. Déployez-la sur votre propre infrastructure et obtenez la cartographie des accès que réclament vos équipes de sécurité et de plateforme.