Secrets et credentials : separation, storage et rotation

Choisir le bon mécanisme d’authentification ne suffit pas.

Une intégration peut utiliser une API key parfaitement adaptée à son modèle d’identité et rester vulnérable si cette clé est stockée au mauvais endroit, partagée avec la configuration ou impossible à renouveler proprement.

La gestion des secrets doit donc être pensée comme un problème à part entière.

Le module structure cette gestion autour de trois pratiques complémentaires :

  1. Separation
  2. Storage
  3. Rotation

Ces trois mécanismes répondent à trois questions différentes :

Separation
→ Le secret est-il séparé de la configuration ?

Storage
→ Où vit réellement la valeur ?

Rotation
→ Peut-on remplacer cette valeur proprement ?

C’est cette combinaison qui permet de passer d’un credential simplement fonctionnel à un credential réellement exploitable en production.


1. Separation : le credential ne doit jamais voyager avec la configuration

Le premier principe est le plus important :

A credential never travels with the configuration that references it.

Autrement dit :

configuration
≠
secret

Une configuration doit contenir uniquement la référence nécessaire pour retrouver le credential au runtime.

Elle ne doit pas contenir sa valeur réelle.


Le mauvais pattern

Prenons un .mcp.json contenant directement une API key :

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

Le problème est mécanique.

Les fichiers de configuration sont souvent :

  • commités ;
  • partagés ;
  • copiés ;
  • clonés ;
  • envoyés dans des pipelines ;
  • conservés dans des sauvegardes.

Si le secret est écrit inline, il suit exactement le même chemin.

On obtient :

.mcp.json
   ↓
repository
   ↓
clone développeur
   ↓
clone CI
   ↓
autres copies

La clé voyage avec le fichier.


Le bon pattern

La configuration doit contenir uniquement une référence :

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

Le fichier sait quel secret demander, mais il ne contient pas ce secret.

On sépare ainsi :

.mcp.json
    ↓
${WAREHOUSE_MCP_TOKEN}

environnement / secret store
    ↓
valeur réelle

Le projet reste partageable sans transporter le credential.


Pourquoi cette séparation est si importante avec Git

Le cas étudié dans le module montre qu’une clé placée dans .mcp.json puis commitée entre immédiatement dans l’historique du repository.

Même si le développeur la retire plus tard, l’ancien commit existe toujours.

C’est pourquoi le problème ne se résume pas à :

« La clé est actuellement visible dans le fichier. »

Il faut se demander :

« Cette valeur a-t-elle déjà été enregistrée dans un système qui conserve un historique ? »

Si la réponse est oui, il faut considérer le credential comme compromis.


Supprimer la valeur ne la rend pas secrète à nouveau

C’est une règle essentielle :

Un secret exposé ne redevient pas secret simplement parce qu’on l’a supprimé.

Une fois la valeur copiée, clonée ou enregistrée dans un historique, on ne sait plus qui a pu la récupérer.

La correction ne consiste donc pas seulement à remettre le secret au bon endroit.

Elle doit aussi inclure une rotation.

Nous y reviendrons.


2. Storage : où doit vivre la valeur ?

Une fois la configuration séparée du credential, une deuxième question apparaît :

Où stocker la véritable valeur ?

Le module distingue principalement deux cas :

  • environment variable ;
  • secret store.

Le choix dépend du nombre de consommateurs, du niveau d’audit attendu et de la durée de vie du secret.


Environment variable : adaptée aux usages locaux ou injectés

Une environment variable est suffisante lorsqu’un credential existe uniquement :

  • sur une machine ;
  • pendant une exécution ;
  • dans un pipeline CI ;
  • ou dans un contexte limité.

Le principe est :

Environment
     ↓
WAREHOUSE_MCP_TOKEN
     ↓
MCP configuration
     ↓
MCP server

La configuration ne voit que le nom de la variable.

La valeur est fournie au runtime.


Exemple en CI

Dans un pipeline, il est préférable que le runner injecte le secret directement dans l’environnement.

Par exemple :

CI secret
   ↓
environment variable
   ↓
WAREHOUSE_MCP_TOKEN
   ↓
.mcp.json

Le credential n’a pas besoin d’être écrit dans un fichier local du runner.

Le module présente explicitement cette approche comme préférable à un fichier de credentials tel que :

/home/jenkins/.config/mcp-credentials.json

si celui-ci contient directement la valeur du secret.


Secret store : pour les secrets partagés ou audités

Lorsqu’un même credential est utilisé par plusieurs personnes ou services, une simple environment variable locale devient moins adaptée.

Le module recommande alors un secret store.

Un secret store permet de :

  • centraliser la valeur ;
  • fournir le secret uniquement aux consommateurs autorisés ;
  • enregistrer les accès ;
  • réduire le nombre de copies ;
  • faciliter la rotation.

On passe d’une architecture distribuée :

Secret
 ├── fichier service A
 ├── fichier service B
 ├── machine développeur
 ├── CI
 └── autre intégration

à une architecture centralisée :

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

Les consommateurs demandent la valeur lorsqu’ils en ont besoin.


Environment variable ou secret store ?

Le module propose un raisonnement simple.

Environment variable

À privilégier lorsqu’un secret :

  • est local ;
  • est temporaire ;
  • n’a qu’un nombre limité de consommateurs ;
  • est injecté au moment de l’exécution.

Secret store

À privilégier lorsqu’un secret :

  • est partagé ;
  • doit être audité ;
  • doit être géré centralement ;
  • est utilisé par plusieurs services ;
  • doit pouvoir être rotated sans multiplier les modifications.

On peut résumer ainsi :

ContexteSolution
Machine localeEnvironment variable
Pipeline CIEnvironment variable
Exécution temporaireEnvironment variable
Plusieurs servicesSecret store
Audit des accès requisSecret store
Gestion centraliséeSecret store

3. Rotation : remplacer le credential sans casser le système

La troisième pratique est la rotation.

La rotation consiste à remplacer un credential existant par une nouvelle valeur.

Elle doit être réalisée :

  • régulièrement ;
  • immédiatement après toute suspicion d’exposition.

Le principe est simple :

ancienne clé
    ↓
révocation
    ↓
nouvelle clé

Mais la facilité avec laquelle cette opération peut être réalisée dépend directement de la qualité de l’architecture précédente.


Pourquoi la rotation devient coûteuse avec des secrets hardcodés

Imaginons une clé écrite directement dans plusieurs fichiers :

service A
→ sk-prod-warehouse-abc123

service B
→ sk-prod-warehouse-abc123

pipeline
→ sk-prod-warehouse-abc123

script local
→ sk-prod-warehouse-abc123

Pour effectuer une rotation, il faut retrouver chaque copie.

Puis modifier chaque système.

Le risque est important :

rotation
   ↓
service oublié
   ↓
panne

C’est exactement ce qui s’est produit dans le scénario du module : deux services externes utilisaient encore la même clé et ont cessé de fonctionner au moment de la rotation.


Pourquoi la séparation facilite la rotation

Avec une variable ou un secret store, le code dépend du nom, pas de la valeur.

Par exemple :

WAREHOUSE_MCP_TOKEN

La configuration continue à utiliser ce nom avant et après la rotation.

Seule la valeur derrière change.

avant
WAREHOUSE_MCP_TOKEN
→ ancienne clé

après
WAREHOUSE_MCP_TOKEN
→ nouvelle clé

Le code ne change pas.

La configuration ne change pas.

Cette séparation rend la rotation beaucoup moins coûteuse.


Un secret compromis doit être rotated immédiatement

Le module insiste sur ce point :

Rotation is the only appropriate response to a leaked key.

Pourquoi ?

Parce qu’un secret exposé ne peut pas être rendu secret à nouveau.

Même si l’on supprime le fichier qui contenait la clé, rien ne garantit que la valeur n’a pas déjà été :

  • copiée ;
  • enregistrée ;
  • clonée ;
  • sauvegardée ;
  • récupérée depuis l’historique Git.

La seule réponse fiable consiste à invalider l’ancienne valeur.


Rotation planifiée et rotation d’incident

Il faut distinguer deux situations.

Rotation planifiée

Le credential est renouvelé régulièrement selon une politique définie.

Rotation après exposition

La rotation doit être déclenchée immédiatement dès qu’une compromission est suspectée.

Le second cas est une réponse à incident.

Il ne faut pas attendre la prochaine date prévue.


Le rôle du least privilege

La gestion des secrets ne s’arrête pas au stockage et à la rotation.

Le module rappelle qu’un credential doit être limité au narrowest access its task needs.

C’est le principe du least privilege.

Imaginons :

Credential A
→ accès complet au warehouse

Credential B
→ lecture limitée à quelques datasets

Si les deux permettent au MCP server d’effectuer sa tâche, le credential B est préférable.

En cas de compromission :

Credential B compromis
       ↓
blast radius limité

Le credential ne doit donc pas seulement être secret.

Il doit aussi être peu puissant.


Ne pas réutiliser le même credential partout

Le scénario du module montre également le danger d’un credential partagé entre plusieurs systèmes.

Une même clé était utilisée par plusieurs services.

Lorsqu’elle a été rotated, plusieurs intégrations ont cassé.

Cela révèle une dépendance excessive.

Plus un credential est partagé :

plus de consommateurs
        ↓
plus grand blast radius
        ↓
rotation plus difficile

L’objectif est donc de limiter le nombre de systèmes dépendant du même secret.


Maintenir un inventaire des consommateurs

Le document recommande de conserver une trace des systèmes qui utilisent chaque credential.

Cette information devient essentielle lors d’une rotation.

Sans inventaire :

rotate key
    ↓
découverte progressive
des services cassés

Avec un inventaire :

credential
   ↓
liste des consommateurs
   ↓
rotation planifiée

La rotation devient une opération maîtrisée plutôt qu’un diagnostic de panne.


Le cas CI : diagnostiquer le vrai problème

Le module fournit une trace de connexion MCP :

[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 lecture superficielle pourrait conclure :

« Il faut simplement remplacer la clé rejetée dans le fichier. »

Mais cela ne corrige qu’un symptôme.

Le problème architectural reste présent :

credential
    ↓
stocké dans un fichier

La correction ciblée

Le module recommande la séquence suivante :

  1. rotate the rejected key ;
  2. remove the credential from the file ;
  3. inject the credential as an environment variable in the CI runner ;
  4. update the MCP configuration to reference that variable.

On corrige donc simultanément :

credential invalide
+
mauvais stockage

C’est un raisonnement important pour l’examen : la meilleure correction n’est pas toujours celle qui rétablit le fonctionnement le plus rapidement.

Il faut aussi supprimer la cause structurelle.


Pourquoi passer à OAuth n’est pas automatiquement la bonne réponse

Dans ce scénario, une autre solution possible serait :

remplacer l’API key par OAuth.

Mais le module montre que ce choix ne découle pas de la trace.

Rien n’indique que le service doive utiliser une user identity.

S’il fonctionne légitimement avec une service identity, une API key reste appropriée.

Le problème est son stockage et sa rotation.

Il faut donc éviter le raisonnement :

problème d'API key
       ↓
OAuth forcément meilleur

Le bon raisonnement est :

Quel modèle d'identité ?
       ↓
Quel mécanisme adapté ?
       ↓
Où stocker le credential ?
       ↓
Comment le rotate ?

Protéger la configuration contre les secrets inline

Le document ne s’arrête pas à la gestion manuelle des secrets.

Il recommande également d’empêcher Claude Code d’inscrire directement un credential dans .mcp.json.

Deux niveaux sont proposés.


CLAUDE.md : communiquer la politique

Une règle peut être ajoutée dans CLAUDE.md :

Never write credential values inline in .mcp.json.

Use environment variable references instead.

Cela permet au modèle de connaître la convention du projet.

Mais cette règle reste une instruction.

Elle n’est pas une garantie technique.


PreToolUse hook : faire respecter la politique

Pour renforcer la sécurité, un PreToolUse hook peut inspecter les opérations d’écriture ou d’édition.

Le principe est :

Claude veut écrire .mcp.json
          ↓
      PreToolUse
          ↓
recherche de pattern credential
        /      \
      oui       non
       ↓         ↓
     block      allow

Le module explique que ce mécanisme permet de bloquer l’opération avant son exécution.


Instruction vs enforcement

Cette distinction est fondamentale :

CLAUDE.md
→ dit ce qui doit être fait

Hook
→ contrôle ce qui peut être fait

Pour une convention de style, une instruction peut suffire.

Pour empêcher une fuite de credential, un contrôle déterministe est plus approprié.


Les trois pratiques réunies

On peut maintenant assembler le modèle complet.

Separation

.mcp.json
→ référence
→ ${WAREHOUSE_MCP_TOKEN}

Storage

usage local / CI
→ environment variable

usage partagé / auditable
→ secret store

Rotation

exposition
→ révoquer
→ nouvelle valeur

Le tout complété par :

least privilege
+
inventaire des consommateurs
+
enforcement via hook

La chaîne de sécurité complète

Une architecture plus robuste ressemble donc à ceci :

.mcp.json
    ↓
référence variable
    ↓
environment variable / secret store
    ↓
credential limité
    ↓
MCP server

Autour de cette chaîne :

CLAUDE.md
→ convention

PreToolUse hook
→ blocage des credentials inline

rotation policy
→ renouvellement

inventory
→ connaissance des consommateurs

La sécurité ne dépend ainsi plus d’une seule bonne pratique.

Elle repose sur plusieurs couches complémentaires.


Ce qu’il faut retenir pour la certification

Pourquoi séparer secret et configuration ?

Parce que les fichiers de configuration sont souvent commités, partagés et clonés.

Le secret ne doit pas suivre ces copies.


Une clé a été supprimée d’un commit ultérieur : est-elle sûre ?

Non.

Elle reste potentiellement présente dans l’historique Git.

Elle doit être considérée comme compromise et rotated.


Environment variable ou secret store ?

Environment variable pour un secret local, temporaire ou injecté dans un pipeline.

Secret store pour un secret partagé, centralisé ou devant être audité.


Pourquoi la rotation est-elle plus simple avec une variable ?

Parce que le code dépend du nom de la variable, pas de la valeur du credential.


Une clé exposée peut-elle être remise en sécurité sans rotation ?

Non.

Une valeur exposée ne peut pas redevenir secrète.


Pourquoi limiter les permissions du credential ?

Pour réduire le blast radius en cas de compromission.


Pourquoi inventorier les consommateurs ?

Pour éviter que la rotation ne casse des systèmes inconnus.


Comment empêcher Claude Code d’écrire un secret inline ?

Utiliser :

CLAUDE.md
+
PreToolUse hook

L’un communique la règle.

L’autre l’impose.


Piège d’examen

Un scénario peut proposer :

Un API key utilisé par un MCP server ne fonctionne plus dans un CI runner. Le credential est stocké dans un fichier local du runner. Quelle correction est la plus appropriée ?

La réponse ne doit pas être limitée à :

mettre une nouvelle clé dans le même fichier

Il faut identifier les deux problèmes :

clé rejetée
+
secret stocké au mauvais endroit

La correction cohérente avec le module est donc :

rotation
+
suppression du secret du fichier
+
environment variable dans le CI runner
+
configuration MCP par référence

Conclusion

La gestion d’un secret ne se résume pas à « cacher une clé ».

Elle doit couvrir tout son cycle de vie.

Le modèle proposé dans le module est :

SEPARATION
    ↓
le secret ne voyage pas avec la config

STORAGE
    ↓
la valeur vit dans un emplacement approprié

ROTATION
    ↓
la valeur peut être remplacée proprement

Puis il faut limiter les conséquences d’un incident :

least privilege
+
nombre limité de consommateurs
+
inventaire
+
contrôles déterministes

Une intégration MCP devient réellement robuste lorsque le credential peut être utilisé sans être exposé, remplacé sans modifier le code et compromis sans ouvrir un accès plus large que nécessaire.


Dans la suite de la série

OAuth et MCP : réussir le passage du staging à la production

Nous verrons pourquoi une intégration OAuth peut fonctionner parfaitement en staging puis échouer immédiatement en production, comment fonctionnent les redirect URIs et pourquoi certains environnements imposent des OAuth app registrations distinctes.

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.