Claude Code & MCP : sécuriser les clés API et les fichiers de configuration

Une API key placée directement dans un fichier .mcp.json peut sembler être un raccourci acceptable pendant le développement.

Le MCP server fonctionne, la connexion est établie et l’on prévoit de déplacer le secret dans une variable d’environnement « plus tard ».

Le problème commence lorsque cette configuration est commitée.

À partir de cet instant, le credential ne se trouve plus seulement sur la machine du développeur : il voyage avec le repository.

Cet exemple illustre un principe essentiel de sécurité avec Claude Code et MCP :

Un credential ne doit jamais voyager avec la configuration qui le référence.

Voyons pourquoi, comment corriger cette architecture et surtout comment empêcher Claude Code de reproduire accidentellement ce type d’erreur.


Le scénario : une API key dans .mcp.json

Un développeur doit connecter Claude Code à un data warehouse MCP server.

Le serveur utilise une API key associée à un service account.

Pour faire fonctionner rapidement la connexion, le développeur écrit directement la clé dans .mcp.json.

La configuration ressemble à ceci :

{
  "type": "http",
  "url": "https://warehouse.internal/mcp",
  "headers": {
    "Authorization": "Bearer sk-abc123..."
  }
}

Techniquement, cela fonctionne.

Le MCP client peut envoyer le credential dans le header Authorization et accéder au serveur.

Le développeur prévoit de déplacer ensuite la clé dans une environment variable.

Mais avant cette correction, .mcp.json est ajouté au repository afin que les autres membres de l’équipe puissent récupérer automatiquement la configuration.

La clé API est donc commitée avec le fichier.


Le credential commence à se propager

Dans le scénario du module, trois membres de l’équipe clonent le repository dans les 48 heures suivantes.

Un pipeline CI effectue également un clone.

La clé se retrouve alors dans plusieurs endroits :

Machine du développeur
        │
        ├── Repository Git + historique
        │
        ├── Machine développeur 2
        │
        ├── Machine développeur 3
        │
        ├── Machine développeur 4
        │
        └── CI runner

Le problème n’est donc plus limité au fichier original.

Le credential est désormais distribué avec le projet.

C’est précisément ce que doit éviter une architecture correcte de gestion des secrets.


« Je supprime la clé et je recommite » : pourquoi cela ne suffit pas

Le développeur découvre l’erreur.

Il modifie immédiatement .mcp.json.

La clé est supprimée et remplacée par une variable d’environnement.

Puis il effectue un nouveau commit.

La version actuelle du fichier ne contient effectivement plus le secret.

Mais l’ancien commit existe toujours.

Git conserve l’historique.

Le credential reste donc récupérable depuis cet historique.

C’est un principe essentiel :

Écraser ou supprimer un credential dans un commit ultérieur ne supprime pas le credential de l’historique du repository.

Il faut donc considérer une clé commitée comme compromise.


La conséquence : rotation obligatoire

Une fois le credential exposé, le remettre dans un emplacement sécurisé ne suffit plus.

Il faut effectuer une rotation.

Cela signifie :

  1. invalider l’ancien credential ;
  2. générer une nouvelle valeur ;
  3. fournir cette nouvelle valeur aux systèmes autorisés.

Dans le scénario étudié, cette rotation provoque un problème supplémentaire.

Deux services externes utilisent également la même clé.

Ils cessent donc de fonctionner lorsque l’ancien credential est révoqué.

Il faut trois heures à l’équipe pour identifier et réparer les différents consommateurs.

Cet incident révèle deux problèmes différents :

Problème 1
Credential stocké dans la configuration

Problème 2
Même credential utilisé par plusieurs consommateurs
sans gestion suffisamment claire de ses dépendances

La bonne configuration .mcp.json

La correction consiste à ne jamais inscrire la valeur du credential directement dans la configuration.

Au lieu de ceci :

{
  "type": "http",
  "url": "https://warehouse.internal/mcp",
  "headers": {
    "Authorization": "Bearer sk-abc123..."
  }
}

on utilise :

{
  "type": "http",
  "url": "https://warehouse.internal/mcp",
  "headers": {
    "Authorization": "Bearer ${WAREHOUSE_MCP_TOKEN}"
  }
}

La différence est fondamentale.

.mcp.json ne contient plus le credential.

Il contient seulement le nom permettant de le retrouver au runtime.

Le secret réel est stocké ailleurs.


Le principe : séparer configuration et secret

On obtient alors cette architecture :

.mcp.json
        │
        │ référence
        ▼
${WAREHOUSE_MCP_TOKEN}
        │
        │ résolution au runtime
        ▼
credential réel

Le repository peut contenir .mcp.json.

Il peut être cloné par dix ou cent développeurs.

La valeur du secret ne voyage pas avec lui.

C’est la première pratique fondamentale du module :

Separation

Le credential ne doit jamais voyager avec la configuration qui le référence.


Où stocker la véritable valeur ?

Une fois le secret sorti du fichier, il faut décider où le conserver.

Le document distingue principalement deux solutions :

  • environment variable ;
  • managed secret store.

Le choix dépend du contexte.


Cas 1 : environment variable

Une environment variable convient lorsqu’un secret est utilisé localement ou injecté au moment de l’exécution.

Par exemple :

WAREHOUSE_MCP_TOKEN=...

Claude Code ou le MCP client récupère ensuite cette valeur lorsque .mcp.json référence :

${WAREHOUSE_MCP_TOKEN}

Cette approche est également adaptée à un pipeline CI.

Le système CI peut injecter le secret dans l’environnement du runner sans placer sa valeur dans le repository.

On obtient :

CI secret
    ↓
environment variable
    ↓
MCP configuration
    ↓
MCP server

Le credential n’a pas besoin d’être écrit dans le projet.


Cas 2 : secret store

Lorsque plusieurs personnes ou services utilisent le même secret, le document recommande plutôt un secret store.

Un secret store est un service géré qui :

  • conserve les credentials ;
  • les fournit aux consommateurs autorisés au runtime ;
  • centralise leur gestion ;
  • permet de savoir qui accède à quoi ;
  • facilite leur rotation.

Cette centralisation évite un problème classique :

Secret
 ├── fichier service A
 ├── fichier service B
 ├── fichier service C
 ├── pipeline
 └── machine développeur

Avec un secret store, on cherche plutôt à obtenir :

              Secret store
             /     |      \
            /      |       \
     Service A  Service B  Pipeline

Les consommateurs récupèrent la valeur lorsqu’ils en ont besoin.


Environment variable ou secret store ?

Le raisonnement proposé par le module peut être résumé ainsi :

SituationSolution
Secret utilisé localementEnvironment variable
Secret injecté dans un pipelineEnvironment variable
Secret temporaire lié à une exécutionEnvironment variable
Secret partagé entre plusieurs servicesSecret store
Besoin de gestion centraliséeSecret store
Besoin d’audit des accèsSecret store

Ce n’est donc pas simplement une question de technologie.

Il faut choisir le mécanisme correspondant au cycle de vie du credential.


La troisième pratique : rotation

Après separation et storage, le troisième principe est la rotation.

La rotation consiste à remplacer régulièrement un credential et à le remplacer immédiatement après toute suspicion d’exposition.

Le point essentiel est le suivant :

Un credential exposé ne peut pas redevenir secret.

Si quelqu’un a pu récupérer une API key, supprimer la copie visible ne permet pas de savoir si cette valeur a déjà été copiée ailleurs.

Il faut donc la remplacer.


Pourquoi une bonne architecture facilite la rotation

Supposons que l’application contienne directement :

sk-prod-warehouse-abc123

Changer cette clé nécessite de retrouver tous les endroits où elle a été copiée.

Avec une variable :

WAREHOUSE_MCP_TOKEN

le code ne dépend plus de la valeur.

On peut avoir :

WAREHOUSE_MCP_TOKEN
        ↓
ancienne valeur

puis :

WAREHOUSE_MCP_TOKEN
        ↓
nouvelle valeur

Le code et .mcp.json n’ont pas besoin d’être modifiés.

C’est l’un des principaux bénéfices opérationnels de la séparation entre configuration et secret.


Appliquer le least privilege

Le module ajoute une autre bonne pratique : chaque credential doit avoir le minimum de permissions nécessaire.

C’est le principe du least privilege.

Imaginons deux clés.

Clé A
→ accès administrateur au data warehouse

Clé B
→ lecture uniquement sur les données nécessaires

Si l’intégration MCP a uniquement besoin de lire certaines données, lui attribuer la clé A augmente inutilement le risque.

Le credential doit être limité à la tâche qu’il sert.

Ainsi, même en cas de compromission, le blast radius reste plus faible.


Connaître les consommateurs d’un credential

L’incident décrit dans le module révèle également un problème organisationnel.

Lorsque la clé est remplacée, deux autres services cessent de fonctionner.

Pourquoi ?

Parce qu’ils utilisaient également ce credential.

Pour rendre une rotation prévisible, il faut donc savoir :

Quels services utilisent cette clé ?

Maintenir cette information réduit le risque de découvrir les dépendances uniquement au moment où la rotation casse la production.


Empêcher Claude Code d’écrire un credential dans .mcp.json

La gestion correcte des secrets règle le problème architectural.

Mais une autre question apparaît :

Comment empêcher Claude Code de réintroduire accidentellement une clé inline ?

Le module recommande deux niveaux de protection.


Première couche : CLAUDE.md

On peut inscrire la convention de sécurité dans CLAUDE.md.

Par exemple :

## Credentials

Never write credential values inline in .mcp.json.

Credentials must be supplied through environment
variables or an approved secret-management mechanism.

Cette règle devient alors une instruction du projet.

Claude Code peut en tenir compte pendant les sessions.

Mais il existe une limite importante.

CLAUDE.md fournit une instruction au modèle.

Ce n’est pas une barrière technique déterministe.


Deuxième couche : PreToolUse hook

Pour une règle de sécurité critique, le document recommande d’ajouter un PreToolUse hook.

Le principe est le suivant :

Claude veut modifier .mcp.json
          ↓
     PreToolUse
          ↓
inspection de l'opération
          ↓
   credential détecté ?
       /          \
     oui           non
      ↓             ↓
   BLOCK          ALLOW

Le hook inspecte les opérations d’écriture ou d’édition concernant .mcp.json.

S’il détecte un pattern ressemblant à un credential inline, il bloque l’opération.

Le document indique qu’un PreToolUse hook peut bloquer un tool call avant son exécution en sortant avec le code approprié.


CLAUDE.md vs Hook : distinction fondamentale

C’est l’un des concepts les plus importants à retenir.

CLAUDE.md

Communique l’intention :

« Ne mets jamais de credentials inline. »

PreToolUse hook

Applique la politique :

« Une opération contenant un credential inline ne sera pas exécutée. »

On peut résumer :

CLAUDE.md
     ↓
Instruction
     ↓
comportement attendu du modèle


PreToolUse hook
     ↓
Enforcement
     ↓
comportement imposé par le système

Pour une convention de code, une instruction peut être suffisante.

Pour une barrière de sécurité critique, un mécanisme déterministe est plus robuste.


Exemple : credential stocké sur un CI runner

Le module propose également une trace d’authentification de ce type :

[MCP Client] Connecting to https://data-api.internal/mcp ...

[MCP Client] GET /auth/token, 401 Unauthorized

[MCP Client] Reading credential from:
  /home/jenkins/.config/mcp-credentials.json

[MCP Client] Credential value:
  WAREHOUSE_TOKEN=sk-****[redacted]

[MCP Client] Retrying with credential, 401 Unauthorized

[MCP Client] Connection failed after 3 attempts

Une réponse superficielle serait :

Remplacer simplement la clé dans mcp-credentials.json.

Mais cela conserverait le défaut architectural.

Le credential resterait stocké dans un fichier.

La correction proposée consiste à :

  1. effectuer une rotation de la clé rejetée ;
  2. retirer le credential du fichier ;
  3. injecter la nouvelle valeur comme environment variable dans le CI runner ;
  4. faire référencer cette variable par la configuration MCP.

On corrige donc simultanément l’incident et sa cause structurelle.


Les trois règles à retenir

La gestion des secrets présentée dans le module peut finalement être résumée par trois concepts.

1. Separation

credential ≠ configuration

Le secret ne doit jamais voyager avec le fichier qui le référence.

2. Storage

Secret local / CI
→ environment variable

Secret partagé / auditable
→ secret store

Le secret doit disposer d’un emplacement adapté à son usage.

3. Rotation

credential exposé
        ↓
     rotation
        ↓
nouveau credential

Une valeur compromise doit être remplacée.


Ce qu’il faut retenir pour la certification

Plusieurs raisonnements sont particulièrement importants dans un scénario d’examen.

Une clé a été commitée puis supprimée dans le commit suivant

La clé doit toujours être considérée comme compromise.

Elle reste dans l’historique du repository.

Un .mcp.json doit être partagé avec toute l’équipe

Le fichier peut contenir une référence à une environment variable, mais pas la valeur du credential.

Plusieurs services utilisent le même secret et celui-ci doit être auditable

Un managed secret store est plus adapté qu’une multiplication des copies du secret.

Une API key vient d’être exposée

Elle doit être rotated.

La remettre simplement dans un emplacement sécurisé ne suffit pas.

Claude Code ne doit jamais inscrire de credentials dans .mcp.json

Une instruction dans CLAUDE.md explique la règle.

Un PreToolUse hook permet de l’imposer de façon déterministe.

Une intégration dispose de permissions beaucoup plus larges que nécessaire

Il faut appliquer le least privilege afin de réduire le blast radius en cas de compromission.


Le piège classique

Face à une règle de sécurité, il faut toujours distinguer :

Ce que Claude devrait faire
          ≠
Ce que le système lui permet de faire

Cette distinction dépasse largement la gestion des API keys.

Elle constitue un principe général pour concevoir des systèmes agentiques sûrs :

Les instructions orientent le comportement du modèle ; les contrôles déterministes imposent les limites de sécurité.


Conclusion

Une API key écrite directement dans .mcp.json transforme un fichier de configuration partageable en vecteur de propagation du secret.

La bonne architecture consiste à séparer les responsabilités :

.mcp.json
    ↓
référence le secret
    ↓
environment variable
ou secret store
    ↓
credential réel

Puis à protéger cette architecture côté Claude Code :

CLAUDE.md
    ↓
communique la règle

PreToolUse hook
    ↓
impose la règle

Enfin, trois pratiques structurent le cycle de vie du secret :

Separation → Storage → Rotation

Ce modèle permet non seulement de réduire le risque de fuite, mais aussi de rendre les credentials plus faciles à partager correctement, à auditer et à remplacer lorsqu’un incident survient.


Dans la suite de la série

MCP : choisir le bon transport et le bon scope

Nous verrons pourquoi stdio et HTTP répondent à des scénarios différents, comment distinguer les scopes Local, Project et Enterprise, et pourquoi une configuration techniquement valide peut malgré tout être inadaptée au mode de déploiement recherché.

Le phare info – Média indépendant & critique
Sélectionne, organise, contextualise et partage des contenus pertinents autour d’un thème ou d’une problématique, dans une logique de veille, de transmission et de mise en sens.
Pour cet article, l’intelligence artificielle a été utilisée comme un outil d’aide à l’exploration, à la structuration et à la rédaction. Elle permet de confronter plusieurs angles, de repérer certains biais humains possibles et de faire émerger des points de vigilance. Le curateur humain observe aussi les biais possibles de l’IA, vérifie les éléments essentiels, nuance l’analyse, corrige les formulations fragiles et assume la publication.

Articles liés

Fiche de révision certification — Accelerators & IP Contribution

Cette fiche résume les notions essentielles du module Accelerators & IP Contribution. Le fil conducteur est simple : Un build Claude n’est pas terminé lorsqu’il fonctionne....

Étude de cas : corriger un accelerator Claude mal packagé, mal versionné et mal sécurisé

Un système Claude peut fonctionner parfaitement en démonstration et pourtant être impropre à la production. Le cas cumulatif du module illustre précisément cette situation. L’application : s’exécute...

Applications Claude multi-composants : trust boundaries, least privilege et sécurité

Une application Claude moderne n’est souvent pas constituée d’un seul appel API. Elle peut combiner : une API applicative ; Claude ; un agent ; Claude Code ; un MCP...

Comparer les plateformes Claude : latency, compliance, data residency et total cost

Lorsque plusieurs plateformes permettent d’exécuter Claude, comment choisir ? Une comparaison superficielle pourrait se limiter à : la plateforme la moins chère ; celle que l’équipe connaît...

Model versioning avec Claude : pin what ships, eval gates et rollback

Changer de modèle dans une application Claude peut sembler être une modification minime : model = "new-model" Pourtant, en production, ce changement peut modifier : la qualité...

Le sentier du savoir

De la curiosité à la transmission, explorez les étapes qui permettent de transformer l’information en compréhension durable.

Étape 1 — Construire une culture générale solide

Construire une base solide de connaissances pour comprendre le monde. Relier les faits, les disciplines et les repères essentiels.

Étape 2 — Maîtriser la pensée critique et l’analyse : apprendre à penser contre ses propres certitudes

Apprendre à analyser l’information, repérer les biais et questionner les évidences. Penser par soi-même dans un monde saturé de récits.

Étape 3 – Apprendre à argumenter et à convaincre

Structurer sa pensée pour convaincre sans manipuler. Savoir débattre, nuancer et formuler des idées claires.

Étape 4 – Approfondir un ou plusieurs domaines d’expertise

Explorer un ou plusieurs domaines en profondeur. Passer de la curiosité à la compréhension experte.

Etapes 5 : Devenir polyglotte : élargir sa pensée par les langues

Élargir ses horizons par le langage et les cultures. Penser autrement en changeant de langue.

Étape 6 — Comprendre la méthode scientifique et expérimenter

Comprendre la méthode scientifique et l’expérimentation. Distinguer savoirs établis, hypothèses et croyances.

Étape 7 – Écrire, transTransmission : écrire, transmettre, enseigner

Écrire, expliquer, partager ce que l’on a compris. Transformer le savoir en outil collectif.

Étape 8 — Cultiver l’équilibre corps-esprit pour soutenir l’érudition

Cultiver le corps et l’esprit pour soutenir l’érudition dans le temps. Le savoir durable repose aussi sur l’attention et l’équilibre personnel.