Sortez les agents MCP des variables d'environnement : migrez les identifiants
Sortez les agents MCP des variables d'environnement en cartographiant les outils, en plaçant les identifiants dans un coffre, en testant les limites des secrets et en renouvelant les anciens jetons en toute sécurité.

Placer des identifiants dans l'environnement d'un serveur MCP est un raccourci qui devient dangereux dès qu'un agent peut exécuter des commandes, inspecter des fichiers, diagnostiquer des erreurs ou lancer des assistants. Le problème n'est pas que chaque agent affichera volontairement un jeton. Le problème est que vous avez donné un secret réutilisable à un processus conçu pour explorer et agir, puis vous lui demandez de se comporter comme s'il ne pouvait pas le voir.
Sortez l'autorité du processus de l'agent. Laissez l'agent demander une action HTTP ou SSH définie, puis laissez un composant local qui détient l'identifiant l'exécuter. Le changement semble minime, mais il vous oblige à déterminer ce que fait réellement chaque outil, quelle identité il lui faut et comment prouver que le jeton ne s'est pas glissé dans le nouveau chemin.
J'ai vu des migrations échouer parce qu'une personne avait supprimé API_TOKEN d'un fichier de configuration tout en le laissant dans un profil shell, un outil d'exécution de tâches ou un modèle de projet copié. L'appel API fonctionnait toujours, tout le monde s'est détendu et l'agent possédait encore l'ancien identifiant. Une migration propre traite la découverte, le remplacement et la preuve comme trois tâches distinctes.
Les variables d'environnement donnent à l'agent plus d'autorité que l'outil n'en a besoin
Une variable d'environnement n'appartient pas à une seule requête. Elle appartient à un processus et souvent à tout ce que ce processus lance. Si un client MCP démarre un serveur avec SERVICE_TOKEN dans son environnement, ce serveur peut le lire. Les processus enfants qui en héritent le peuvent aussi, sauf si quelqu'un les en prive soigneusement. Les commandes de diagnostic, les rapports d'erreur, les jeux de test et une sortie accidentelle de env peuvent transformer une commodité locale en fuite durable.
C'est différent d'un outil qui reçoit un résultat authentifié. Ce résultat peut contenir une liste de dépôts, l'état d'un déploiement ou une réponse d'erreur. L'agent en a besoin pour poursuivre son travail. Il n'a pas besoin du jeton bearer qui a permis la requête.
La distinction s'estompe parce que les deux architectures peuvent produire la même requête réussie. Elles ne sont pourtant pas équivalentes :
- Possession d'un identifiant : l'agent peut utiliser, copier, transformer ou exfiltrer un secret en dehors de l'appel d'outil prévu.
- Autorité d'action : l'agent peut demander à un exécuteur local de confiance d'effectuer une requête selon des contrôles définis.
- Accès au résultat : l'agent voit la réponse nécessaire pour décider de l'action suivante.
Confondre ces notions mène à une recommandation courante et dangereuse : placer les jetons dans un gestionnaire de secrets, puis les injecter au démarrage dans l'environnement de l'agent. Cela peut améliorer le stockage au repos, mais ne change pas la limite d'exécution. L'agent reçoit toujours le jeton.
La spécification MCP décrit un protocole pour les clients, les serveurs et les outils. Elle ne fait pas des variables d'environnement une limite de sécurité pour les identifiants. Considérez-les comme un moyen de transmettre une configuration locale uniquement lorsque le processus qui les reçoit est déjà autorisé à détenir le secret. Les agents de programmation autonomes ne répondent souvent pas à ce critère.
Dressez l'inventaire des outils avant de modifier la configuration
Commencez par un inventaire écrit. Ne commencez pas par modifier des fichiers JSON, car les fichiers de configuration donnent rarement toute l'histoire. Un outil peut lire directement une variable, appeler un wrapper qui en lit une autre ou dépendre d'un client en ligne de commande qui charge les identifiants depuis un fichier du répertoire personnel.
Pour chaque outil MCP, notez son nom, sa commande, sa cible, sa méthode d'authentification, le propriétaire de l'identifiant, l'étendue des permissions et la requête sans risque utilisable pour les tests. Notez aussi l'endroit où le secret entre actuellement dans le processus : configuration du client, fichier de démarrage du shell, fichier .env, export CI, commande du gestionnaire de mots de passe ou script auxiliaire.
Un inventaire compact peut ressembler à ceci :
| Outil | Cible de l'action | Chemin actuel du secret | Nouvelle limite | Test |
|---|---|---|---|---|
| recherche de tickets | API des tickets | ISSUES_TOKEN dans la configuration du client | action HTTP locale | lister un projet connu |
| état du déploiement | API de déploiement | .env.local | action HTTP locale | lire l'état du service |
| diagnostic de l'hôte | alias d'hôte SSH | chemin du fichier de clé privée | action SSH locale | exécuter uname |
| publication de paquet | API du registre | export shell | action HTTP locale | lire les métadonnées du paquet |
Ne cachez pas des permissions étendues derrière des noms vagues comme prod-token ou default-key. Donnez à l'enregistrement de l'identifiant un nom qui indique à l'opérateur ce qu'il peut faire et où il va. deploy-api-production-read est moins élégant, mais bien plus sûr lors d'une vérification menée dans l'urgence.
L'inventaire montre aussi si l'identifiant devrait exister. J'ai trouvé des jetons capables d'écrire associés à des outils qui ne faisaient que lire des métadonnées de projet, parce que quelqu'un avait copié une configuration de développement. Une migration est le bon moment pour créer des identifiants plus limités. Elle ne justifie pas de conserver toutes les anciennes permissions dans un conteneur plus élégant.
Supprimez l'injection du secret, ne la maquillez pas
Une configuration migrée doit cesser de transmettre le secret à l'agent ou à son serveur MCP. Remplacer un jeton écrit en clair par ${SERVICE_TOKEN}, $(secret-tool lookup ...) ou le chemin d'un fichier non protégé ne suffit pas. Vous avez changé l'écriture, pas l'autorité.
Commencez par rechercher les références actuelles. Dans un répertoire de projet, cette commande trouve de nombreux cas évidents :
rg -n --hidden --glob '! .git' 'API[_-]?KEY|API[_-]?TOKEN|SECRET|PASSWORD|PRIVATE[_-]?KEY|Authorization: Bearer' .
Le résultat attendu est une liste d'entrées au format fichier:ligne:texte correspondant. Ne collez pas ce résultat dans un ticket s'il contient des valeurs actives. Utilisez-le pour établir une liste de corrections, puis recherchez séparément dans les emplacements habituels du compte utilisateur, comme les profils shell et les réglages du client MCP.
Comparez ensuite l'environnement visible par l'ancien processus d'agent avec celui du nouveau. Dans un shell de test contrôlé, listez les noms sans afficher les valeurs :
env | cut -d= -f1 | sort | rg 'TOKEN|KEY|SECRET|PASSWORD'
Les anciens noms doivent avoir disparu du processus qui lance l'agent. Si SERVICE_TOKEN y apparaît, la migration est incomplète, même si le nouveau chemin par la passerelle fonctionne.
Évitez le compromis tentant où le serveur MCP possède le jeton, mais pas l'agent principal. Cela réduit une voie d'exposition, mais le serveur reçoit toujours la possession illimitée de l'identifiant. S'il peut exécuter des commandes arbitraires, charger des extensions ou écrire des journaux, vous avez simplement déplacé le problème vers un processus souvent moins surveillé.
Utilisez une configuration non secrète pour sélectionner les cibles. Une URL de base, un alias d'hôte, un identifiant de compte et le nom d'un identifiant peuvent figurer dans la configuration s'ils n'accordent aucun accès. Gardez les éléments d'authentification dans un coffre local que l'agent ne peut pas interroger comme des données.
Modélisez le nouveau chemin avec des requêtes, des identifiants et des résultats
Le nouveau flux doit avoir une limite claire : l'agent nomme une action et fournit les données ordinaires de la requête, l'exécuteur local sélectionne et injecte l'identifiant, puis renvoie la réponse. L'agent ne reçoit jamais un élément qu'il pourrait résoudre pour obtenir le secret.
Pour un outil HTTP, séparez la forme publique de la requête de l'étape privée d'authentification. L'agent peut demander cette requête :
GET https://api.example.internal/projects/atlas/issues?state=open
L'exécuteur local ajoute l'identifiant bearer, basic ou à en-tête personnalisé approprié, puis renvoie le corps et le statut de la réponse. Si l'agent demande un hôte, une méthode ou un compte non approuvé, l'exécuteur doit refuser la requête au lieu de deviner quel identifiant convient.
Pour SSH, la requête contient un hôte et une commande, tandis que la clé privée reste en local. C'est important, car les outils SSH ont tendance à faire passer l'autorité par des chemins, le transfert d'agent, les inclusions de configuration et la variable héritée SSH_AUTH_SOCK. Un chemin de clé privée dans la configuration de l'outil ne constitue pas un remplacement sûr. L'agent peut souvent lire le fichier, le copier ou modifier la commande qui l'utilise.
Sallyport applique ce modèle grâce à son relais stdio intégré sp mcp : les agents effectuent des appels MCP, tandis que l'application réalise les appels API HTTP et les commandes SSH sans remettre de clés API ou SSH à l'agent. Cette limite n'est utile que si vous supprimez aussi l'ancienne injection dans l'environnement.
Ne transformez pas l'exécuteur local en proxy généraliste doté d'un identifiant tout-puissant. La requête de l'agent doit désigner une destination et un identifiant configurés, et non fournir une URL arbitraire ainsi qu'un choix d'identifiant. Sinon, un agent manipulé par une injection de prompt peut transformer un identifiant légitime en signataire de requêtes vers un endroit que vous n'aviez jamais prévu.
Choisissez des points d'approbation que les personnes peuvent encore évaluer
L'approbation humaine fonctionne lorsqu'une personne comprend ce qu'elle approuve. Elle échoue quand un agent de longue durée génère une série de demandes presque identiques jusqu'à ce que quelqu'un clique machinalement. Cet échec est prévisible. Il vient d'un défaut de conception, pas d'un manque de vigilance de l'opérateur.
Utilisez une approbation au niveau de la session lorsqu'il faut établir qu'un processus d'agent précis peut utiliser les actions configurées pendant une exécution. L'approbation doit identifier le processus d'une façon qui aide à distinguer le véritable client d'une imitation. Le seul nom du processus constitue une preuve faible, car n'importe quel programme peut choisir un nom familier.
Réservez l'approbation par appel aux identifiants dont les conséquences exigent un jugement humain renouvelé. Un accès d'écriture en production, une commande destructive sur un hôte et une API liée aux paiements méritent cette friction. Une simple recherche en lecture seule dans les tickets, généralement non. Si chaque appel d'outil demande une décision, les opérateurs cessent de lire la décision.
Un coffre verrouillé doit refuser les demandes, même si un agent approuvé précédemment fonctionne encore. C'est le rôle de la barrière du coffre. Un processus sans surveillance ne doit pas conserver une autorité simplement parce qu'il la possédait plus tôt dans la journée.
Sallyport propose trois contrôles fixes plutôt qu'un langage de politiques : une barrière de coffre, l'autorisation de chaque nouveau processus d'agent et une approbation facultative à chaque utilisation d'une clé. Ce modèle fixe est volontairement plus étroit qu'un moteur de règles, ce qui réduit le nombre de règles ingénieuses qu'un opérateur fatigué pourrait mal écrire.
Testez séparément la réussite et le secret
Une réponse positive de l'outil prouve seulement que quelque chose a authentifié la requête. Elle ne prouve pas que l'agent ne pouvait pas obtenir l'identifiant. Effectuez une migration qui vérifie ces deux affirmations, en commençant par une action peu risquée.
Pour chaque outil, suivez cette séquence :
- Verrouillez le coffre local et invoquez l'outil. L'appel doit échouer sans utiliser un jeton d'environnement en secours.
- Déverrouillez le coffre, démarrez un nouveau processus d'agent et approuvez-le si votre configuration l'exige. Exécutez la requête sans risque indiquée dans l'inventaire.
- Consultez le journal des actions ou l'enregistrement d'audit côté serveur pour vérifier la destination exacte, le compte, la méthode et le statut du résultat. Confirmez que l'action est enregistrée sans que le secret le soit.
- Depuis le chemin d'exécution autorisé à l'agent, inspectez son environnement à la recherche de l'ancien nom de variable et son espace de travail à la recherche du préfixe du jeton. Le jeton ne doit apparaître dans aucun des deux endroits.
- Redémarrez le processus d'agent et répétez la requête. Vous vérifierez ainsi que vous ne dépendiez pas par accident d'un état hérité de l'ancien shell.
La première étape détecte une erreur discrète, mais grave. Les équipes configurent parfois un chemin vers le coffre tout en conservant l'ancienne variable comme solution de secours. Quand le coffre est verrouillé, l'outil fonctionne quand même. Cela semble fiable, jusqu'à ce que le même secours apparaisse dans un exécuteur CI, un dépôt copié ou une transcription de l'agent.
Ne demandez pas à l'agent d'afficher toutes ses variables d'environnement comme preuve principale. Ce test crée lui-même une voie de divulgation et peut placer l'ancien jeton dans l'historique de la conversation. Vérifiez les noms depuis un shell contrôlé et utilisez, pendant les essais à blanc, une variable marqueur volontairement non secrète si vous devez valider le comportement d'héritage.
Pour SSH, testez une commande qui renvoie des informations inoffensives sur l'identité du système, plutôt qu'une commande qui modifie son état. Confirmez le résultat, puis vérifiez que la configuration de l'agent contient une référence à l'hôte et non le contenu de la clé privée. Examinez aussi la configuration SSH à la recherche de ForwardAgent yes. Le transfert d'agent peut donner à un hôte distant un moyen d'utiliser les identités locales. Il s'agit d'un risque distinct de l'exposition du fichier de clé privée.
Les journaux d'audit doivent permettre de reconstituer une action contestée
Un journal d'action est utile lorsqu'il répond à une question difficile un lundi matin : quelle exécution d'agent a effectué cette requête, avec quel identifiant configuré et une personne l'a-t-elle approuvée ? Une ligne vague comme tool succeeded ne permettra pas de trancher.
Conservez un relevé de session pour les exécutions d'agents et un relevé d'appel pour chaque action. Le relevé de session indique quand un processus a commencé, quelle identité vous avez approuvée et quand vous l'avez révoquée. Le relevé d'appel indique ce qui s'est passé pendant cette session. Ne mélangez pas les deux dans un flux d'événements plat si vous devez enquêter sur une exécution parmi beaucoup d'autres.
La preuve d'altération compte, car un agent disposant d'une exécution locale de commandes peut tenter d'effacer ses traces après une action indésirable. Un journal chaîné par hachage permet de détecter une modification ou une suppression de l'historique, mais uniquement si la vérification ne dépend pas de la coopération de l'agent.
Sallyport produit les deux journaux à partir d'un journal d'audit chiffré, inscriptible sans possibilité de lecture et chaîné par hachage. Il prend en charge la vérification hors ligne de la chaîne chiffrée avec cette commande :
sp audit verify
Un résultat positif doit indiquer que la vérification s'est terminée correctement. En cas d'échec, considérez le journal comme suspect jusqu'à ce que vous compreniez la rupture. La vérification ne dit pas si l'action était judicieuse. Elle indique si le relevé conserve sa continuité.
Gardez les données d'audit hors des prompts du modèle et des conversations ordinaires. Le relevé peut contenir un contexte sensible sur la requête ou des métadonnées de réponse, même s'il ne contient jamais l'identifiant. L'accès aux investigations ne doit pas devenir une porte dérobée pour une consultation sans contrôle.
Le renouvellement est le nettoyage qui prouve que la migration est réelle
Après la réussite des tests de chaque nouveau chemin, renouvelez l'ancien identifiant. Le laisser valide parce que « nous pourrions devoir revenir en arrière » prolonge la période pendant laquelle des configurations oubliées peuvent encore s'authentifier. Concevez le retour arrière autour d'un remplacement contrôlé séparément, et non autour d'un secret déjà diffusé dans les environnements locaux.
L'ordre du renouvellement compte. Créez le nouvel identifiant limité, stockez-le en local, validez le nouveau chemin, supprimez l'ancienne injection du secret, puis révoquez l'ancien identifiant. Si un ancien jeton a pu apparaître dans le contrôle de version, une conversation, un ticket d'assistance ou une sortie de compilation, révoquez-le d'abord et acceptez l'interruption pendant que vous rétablissez un accès sûr.
Répétez la recherche après la révocation. Vous cherchez des références obsolètes, pas des valeurs secrètes actives. Supprimez les anciens noms de variables dans les fichiers d'exemple, les documents d'intégration, les profils shell, les scripts de tâches et les instructions de test. Les futurs développeurs recopient les exemples avec une fidélité surprenante.
Enfin, laissez dans vos notes d'exploitation un test d'échec volontaire : verrouillez le coffre et lancez un appel d'outil sans risque. Si l'appel réussit, quelqu'un a réintroduit un contournement. Ce seul contrôle détecte davantage de mauvaises migrations qu'un nouveau schéma d'architecture bien présenté.
Considérez les identifiants trop larges comme un défaut de conception de l'outil
Déplacer un jeton dans un coffre ne rend pas un jeton étendu adapté à un agent. Cela change seulement celui qui le détient. Un outil capable de consulter les tickets d'un projet ne doit pas posséder discrètement le droit de supprimer des projets, de modifier la facturation ou de déployer du code en production.
Séparez les outils selon le travail réel et ses conséquences. Les actions de découverte en lecture seule peuvent utiliser un identifiant limité et une approbation légère. Les actions qui modifient l'état exigent des portées plus strictes, des cibles explicites et parfois un consentement à chaque appel. L'agent est aussi plus facile à superviser lorsque les verbes disponibles correspondent à la tâche demandée.
Méfiez-vous d'un identifiant universel admin justifié par la simplicité de l'outil. Cette configuration est populaire parce qu'elle réduit le travail aujourd'hui. Elle complique la réponse aux incidents demain, car vous ne pouvez plus distinguer les requêtes qui avaient besoin de cette puissance de celles qui en ont simplement hérité.
La migration est réussie lorsqu'un agent peut accomplir le travail prévu, qu'un coffre verrouillé l'arrête, qu'un nouveau processus doit gagner l'autorité configurée et qu'aucun ancien jeton ne reste dans son environnement. Si l'une de ces affirmations n'a pas de test, vous avez une démonstration fonctionnelle, pas une limite de sécurité pour les identifiants.
FAQ
Pourquoi les variables d'environnement sont-elles dangereuses pour les agents MCP ?
Les variables d'environnement sont pratiques pour un script local, mais elles placent le secret dans l'environnement du processus de l'agent. Un agent peut souvent lire directement cet environnement, le transmettre à un processus enfant ou le faire apparaître dans des informations de diagnostic. Une passerelle d'actions locale garde l'identifiant hors de ce processus et exécute elle-même la requête authentifiée.
Puis-je partager sans risque un fichier de configuration MCP qui utilisait des variables d'environnement ?
Une configuration MCP copiée contient généralement la commande, les arguments et les valeurs d'environnement. Considérez le fichier copié comme une fuite potentielle jusqu'à ce que vous ayez supprimé les valeurs secrètes et révoqué ou renouvelé tout jeton susceptible d'avoir été partagé. Un analyseur de secrets peut aider à trouver des copies, mais il ne peut pas prouver qu'aucune copie n'existe.
Dois-je renouveler les jetons API avant ou après la migration d'un outil MCP ?
Ne renouvelez pas un jeton sans raison. Faites-le après avoir mis en place un chemin de remplacement fonctionnel, puis vérifiez ce chemin avec la requête la moins risquée possible. L'exception concerne un jeton déjà exposé dans un dépôt, un ticket, une conversation ou un journal de compilation public. Révoquez-le immédiatement, puis corrigez le processus.
Un fichier de configuration MCP peut-il contenir une référence à un secret ?
Non. Un fichier de configuration peut indiquer le point de terminaison ou le profil de compte utilisé par un outil, mais il ne doit contenir ni jeton bearer, ni mot de passe, ni clé privée, ni expansion shell qui se résout en secret. Une référence à un identifiant stocké localement n'est acceptable que si l'agent ne peut pas lire cet identifiant à travers cette référence.
Comment vérifier qu'un agent ne peut pas voir un jeton migré ?
Un test convaincant vérifie séparément deux points : l'action demandée réussit et le processus de l'agent ne peut pas obtenir le jeton. Consultez le relevé d'action de la passerelle, puis inspectez l'environnement de l'agent et son répertoire de travail à la recherche de l'ancien nom de variable et du préfixe du jeton. Un appel API réussi ne prouve presque rien à lui seul.
Puis-je aussi retirer les clés SSH de l'environnement d'un agent IA ?
SSH exige la même séparation que les identifiants HTTP. L'agent doit demander une action SSH nommée, tandis qu'un outil local utilise la clé privée sans transmettre le fichier ni son contenu à l'agent. Ne résolvez pas le problème en plaçant dans la configuration de l'agent le chemin d'une clé privée non chiffrée.
Quand un identifiant MCP doit-il exiger une approbation à chaque appel ?
L'approbation par session établit quel processus d'agent peut effectuer des appels pendant une exécution. L'approbation par appel concerne les identifiants ou les actions qui méritent une décision humaine à chaque fois, par exemple un accès au déploiement en production ou une API liée aux paiements. Exiger une approbation pour chaque lecture sans risque pousse les utilisateurs à approuver machinalement.
Que se passe-t-il lorsque le coffre local est verrouillé pendant l'exécution d'un agent ?
Non, si le coffre est verrouillé et refuse les actions pendant ce verrouillage. Ce comportement est volontaire : un agent sans surveillance ne doit pas gagner un accès simplement parce qu'il continue de fonctionner. Pour les tâches longues, divisez le travail en phases faciles à examiner au lieu d'essayer de contourner la limite imposée par le verrouillage.
Quel est le plan de retour arrière le plus sûr pour une migration d'identifiants MCP ?
Le retour le plus sûr consiste à désactiver la nouvelle entrée de l'outil, et non à rétablir une variable d'environnement secrète. Gardez l'ancien identifiant à la disposition d'un administrateur pendant une courte période de migration, puis révoquez-le lorsque le nouveau chemin a passé les tests. Si vous devez rétablir l'ancien chemin, utilisez un jeton nouvellement créé et limité, plutôt qu'un jeton dont vous soupçonnez l'exposition.
Les journaux d'audit rendent-ils les identifiants d'agents autonomes sûrs ?
Un journal d'audit aide à reconstituer quelle session d'agent a invoqué quelle action, à quel moment, et si la demande a été approuvée ou refusée. Il ne rend pas à lui seul un identifiant étendu sûr. Il faut aussi des permissions limitées, une sélection correcte de la cible et une séparation qui empêche l'agent de lire l'identifiant.