Les agents de code comme Claude Code, Cursor ou Codex ont besoin de mots de passe de base de données et de clés d'API pour déployer, migrer et tester. Les façons habituelles de les transmettre placent la valeur dans le contexte de l'agent, puis dans les journaux de session sur le disque et dans les requêtes envoyées au fournisseur du modèle. Ce guide montre où la valeur fuit, quelles règles la tiennent vraiment à l'écart et comment mettre cela en place en quelques minutes.
Un agent travaille en lançant des outils et en lisant leur sortie. Cette sortie fait partie de la conversation : elle est envoyée au modèle avec chaque requête suivante et écrite dans le journal de session sur votre machine. Une valeur qui y apparaît une fois y reste, bien après la fin de la tâche. Dans notre propre mesure, 68 des 70 secrets de déploiement se sont retrouvés en clair dans les journaux de session d'un agent de code en quatre semaines, et aucun n'avait été tapé dans le chat.
Le schéma est toujours le même : l'agent ne fait rien de mal, un outil affiche la valeur et l'agent lit ce que les outils affichent.
Les commandes run comme op run de 1Password ou doppler run respectent déjà la première règle : elles injectent la valeur dans un processus au lieu de l'afficher, et op run la masque en plus dans la sortie. Utilisez-les plutôt que les commandes read ou get. Ce qu'elles ne couvrent pas, c'est le moment où la valeur manque : sans le chat, l'agent ne peut pas vous la demander, et rien ne lie la valeur à la commande à laquelle elle était destinée.
vault-ask est un petit outil open source en ligne de commande avec serveur MCP, pour Node.js 20 ou plus récent, sans dépendances.
npm install -g @erseni/vault-ask L'agent demande la valeur pour exactement une commande :
vault-ask DB_PASSWORD -- psql -h db.example.com -U app vault-ask affiche un lien. Vous l'ouvrez dans votre navigateur, voyez la commande à laquelle la valeur est destinée et la saisissez. Elle arrive chiffrée de bout en bout, va uniquement dans l'environnement de cette commande, et l'agent ne voit qu'une ligne comme « DB_PASSWORD received, 32 characters, passed to the command ».
Pour les outils qui lisent un fichier, la valeur va dans un fichier .env ou dans un seul fichier aux droits 600 :
vault-ask STRIPE_KEY SENTRY_DSN --env-file .env vault-ask TLS_KEY --file certs/server.key Dans Claude Code, ajoutez le serveur MCP une seule fois. Ensuite, l'agent demande lui-même les secrets au lieu de vous demander de les coller :
claude mcp add vault-ask -- npx -y @erseni/vault-ask mcp Dans Cursor ou un autre client MCP, ajoutez le serveur à la configuration MCP (pour Cursor dans ~/.cursor/mcp.json) :
{ "mcpServers": { "vault-ask": { "command": "npx", "args": ["-y", "@erseni/vault-ask", "mcp"] } } } Une valeur écrite dans un fichier peut encore être lue plus tard. Pour Claude Code, vault-ask fournit donc vault-ask-guard, un hook PreToolUse qui refuse de lire les fichiers écrits par vault-ask et refuse des commandes comme env ou echo comme cible. Ajoutez-le à .claude/settings.json :
{ "hooks": { "PreToolUse": [ { "matcher": "Bash|Read|Edit|MultiEdit|Write|Grep|Glob|NotebookEdit|mcp__vault-ask__run_with_secret|mcp__vault-ask__send_secret", "hooks": [{ "type": "command", "command": "vault-ask-guard" }] } ] } } Ces règles rattrapent les accidents et rendent visible un agent manipulé, puisqu'il devrait vous redemander la valeur pour chaque nouvelle commande. Elles n'arrêtent pas un agent qui tourne sous votre propre utilisateur système avec un shell et lit délibérément la mémoire ou l'environnement d'un processus qu'il a lancé. Une protection complète exige une séparation des privilèges : le secret est détenu par un service sous un autre utilisateur et l'agent n'en détient qu'une référence.