SSD Nodes Learn Hosting plans →
Guides Matt ConnorPar Matt Connor · Mis à jour le 2026-08-22

Comment protéger les secrets de vos agents IA

Une clé d’API dans l’environnement d’un agent peut fuir en un appel d’outil. Utilisez une credential gateway, des tokens courts et des droits limités.

Ce que signifie garder les secrets hors des agents IA

Un agent IA est un processus Linux normal qui exécute des commandes. Toutes les variables d’environnement détenues par ce processus sont lisibles par le code qu’il exécute. Une clé d’API présente dans l’environnement de l’agent est donc une clé que l’agent peut envoyer à n’importe quel hôte qu’il peut atteindre. Garder les secrets hors de l’agent consiste à lui fournir un handle plutôt que la clé : un jeton à durée de vie courte et aux droits limités, ou un placeholder qu’un autre composant remplace par la valeur réelle à la frontière réseau.

Il ne s’agit pas d’un modèle qui devient hostile. Le mécanisme est plus banal. Un agent lit une page web, un README ou un commentaire d’issue contenant des instructions, puis les suit, car un modèle de langage ne fait pas la différence entre le texte que vous avez écrit et celui qu’il a récupéré. C’est une prompt injection. Une fois qu’elle se produit, l’ampleur des dommages dépend d’une seule chose : ce que le processus peut lire. Si vous n’avez pas encore défini de limite, exécuter un agent de programmation en toute sécurité sur un serveur présente les niveaux d’isolation sur lesquels repose ce guide.

Le modèle de menace en termes simples

Exécutez cette commande avec l’utilisateur sous lequel votre agent s’exécute.

tr '\0' '\n' < /proc/self/environ | grep -iE 'key|token|secret|password'

Chaque ligne qu’il affiche correspond à une requête HTTP pouvant atteindre le serveur d’un tiers. Examinez maintenant ce qui se trouve sur le disque, à proximité de l’agent.

grep -rIl --exclude-dir=.git -e 'API_KEY' -e 'SECRET' ~/projects
find ~ -maxdepth 3 -name '.env' -o -name 'credentials' -o -name '*.pem'

Un agent qui dispose d’un shell n’a pas besoin d’un exploit sophistiqué pour exfiltrer ces données. Quatre méthodes courantes suffisent, et les quatre ressemblent à des opérations normales dans les journaux :

  • Un curl ou fetch sortant vers n’importe quel hôte, avec la valeur dans une chaîne de requête.
  • Un git commit et un git push vers un dépôt dans lequel l’agent peut écrire.
  • Un script d’installation de paquet, qui exécute du code arbitraire avec les droits de l’utilisateur de l’agent.
  • Une résolution DNS d’un nom d’hôte contenant la valeur, qui aboutit même lorsque les connexions HTTP sortantes sont bloquées.

Vous ne pouvez pas résoudre ce problème par une simple revue. La solution consiste à s’assurer qu’aucune donnée précieuse ne soit accessible.

Un secret présent dans l’arborescence de travail est un secret présent dans la fenêtre de contexte

Un agent lit des fichiers. Un fichier .env présent dans le dépôt sur lequel il travaille sera lu. Dès sa lecture, il se trouve dans la fenêtre de contexte. Il figure donc dans la transcription, dans tous les journaux que vous conservez et dans tout ce que l’agent écrira ensuite.

Avant, lorsque la clé se trouvait dans l’arborescence de travail de l’agent :

cd ~/projects/billing
cat .env
# STRIPE_SECRET_KEY=sk_live_...
# DATABASE_URL=postgres://app:hunter2@db.internal:5432/billing

Après avoir déplacé le fichier hors de sa portée :

sudo install -d -m 750 -o root -g agent-review /etc/agent-review
sudo install -m 640 -o root -g agent-review ~/projects/billing/.env /etc/agent-review/billing.env
rm ~/projects/billing/.env

L’utilisateur de l’agent ne peut plus ouvrir le fichier, car l’arborescence de travail ne le contient plus. Les règles de refus de la configuration de l’agent constituent une deuxième couche, et non la première. Claude Code lit les règles d’autorisation depuis .claude/settings.json dans le projet :

{
  "permissions": {
    "deny": ["Read(./.env)", "Read(./secrets/**)", "Read(./**/*.pem)"]
  }
}

Cela empêche l’agent d’ouvrir accidentellement un fichier pendant son exploration. En revanche, cela n’empêche pas une instruction injectée d’exécuter base64 .env, car il s’agit d’une commande shell et non d’une lecture de fichier. La demande de confirmation avant l’exécution de cette commande dépend du mode d’autorisation de la session. Or le mode automatique devient le mode par défaut de Claude Code en août 2026 : un serveur que vous ne surveillez pas exécutera donc davantage de ces commandes sans confirmation. La même limite s’applique à tout ce qui façonne les habitudes de l’agent plutôt que ses autorisations : une skill qui impose à l’agent de limiter les changements au strict nécessaire empêche une exécution d’explorer des fichiers qu’elle n’avait aucune raison d’ouvrir, mais cela reste une recommandation dont le modèle peut être détourné. Considérez la configuration comme une glissière de sécurité et les permissions du système de fichiers comme un mur. La même distinction s’applique dans les conteneurs : les fichiers env et les secrets dans Docker Compose couvrent la version de ce problème située un niveau plus bas.

Donnez à chaque agent son propre utilisateur non privilégié

Si l’agent s’exécute avec votre compte, il hérite de vos clés SSH, de vos identifiants cloud et de votre historique shell. Un utilisateur distinct ne coûte qu’une commande et supprime tous ces accès.

sudo adduser --disabled-password --gecos "" agent-review
sudo chmod 700 /home/agent-review
sudo -u agent-review cat ~/.ssh/id_ed25519

La dernière ligne doit échouer avec cat: /home/you/.ssh/id_ed25519: Permission denied. Si elle affiche une clé, votre répertoire personnel est lisible par le groupe ou par tous les utilisateurs, et chmod 700 ~ corrige le problème. N’ajoutez pas l’utilisateur de l’agent à sudo et ne lui accordez pas de règle NOPASSWD plus large que la seule commande dont il a réellement besoin. Utilisateurs appliquant le principe du moindre privilège sur un VPS détaille les groupes et sudoers. Gardez cette séparation à l’esprit dès que vous exécutez plusieurs sessions sur la machine, car une session Claude Code peut envoyer du texte directement à une autre, et tout ce que contient la première session peut franchir ce canal en un seul message.

Une autre limite mérite d’être ajoutée sur un VPS cloud. Le service de métadonnées de l’instance répond sur une adresse link-local fixe et fournit souvent des identifiants de rôle à tout ce qui les demande.

sudo iptables -A OUTPUT -m owner --uid-owner agent-review -d 169.254.169.254 -j REJECT

Vérifiez-le depuis l’environnement de l’agent. sudo -u agent-review curl -s --max-time 3 http://169.254.169.254/ ne doit rien afficher et doit se terminer avec un code différent de zéro, car le paquet est rejeté avant de quitter la machine.

Injecter l’identifiant à la frontière

Le mécanisme qui résout réellement ce problème est l’injection d’identifiants. L’agent ne détient jamais de clé réelle. Il envoie sa requête via une passerelle locale, qui remplace un paramètre fictif par le secret réel avant de transmettre la requête. Le secret est stocké par la passerelle, dans un autre processus, exécuté par un autre utilisateur.

OneCLI est une implémentation open source de ce mécanisme, sous licence Apache-2.0. Elle s’exécute dans un conteneur à côté de l’agent. En juillet 2026, le projet documente cette configuration :

git clone https://github.com/onecli/onecli.git
cd onecli
docker compose -f docker/docker-compose.yml up -d --wait

Le dashboard écoute sur le port 10254 et la passerelle sur le port 10255. Vous stockez l’identifiant réel une seule fois, puis vous fournissez à chaque agent une valeur fictive à la place de la clé, ainsi que son propre access token limité, qu’il envoie dans un en-tête Proxy-Authorization. La passerelle identifie la requête sortante d’après l’hôte et le chemin, déchiffre l’identifiant correspondant, puis le substitue. L’environnement de l’agent ne contient rien qui puisse être récupéré utilement.

L’intérêt ne réside pas dans le chiffrement. Il réside dans le fait que la question « qu’a utilisé cet agent, et quand ? » devient une requête dans les journaux. Vous consultez une seule piste d’audit au lieu d’essayer de deviner lequel des six environnements contenait une copie de la clé.

Transmettez le secret au processus, pas à l’environnement

Si vous exécutez l’agent avec systemd, les variables d’environnement sont inutiles. LoadCredential= place le secret dans un répertoire privé que seul ce service peut lire. Le secret est exposé sous la forme de %d dans le fichier d’unité et de $CREDENTIALS_DIRECTORY à l’intérieur du processus. La valeur n’apparaît jamais dans /proc/<pid>/environ. ps eww ne peut donc pas l’afficher. Le répertoire disparaît lorsque le service s’arrête.

Chiffrez d’abord l’identifiant pour cette machine. Ces commandes proviennent de la documentation systemd et fonctionnent avec systemd 250 ou une version ultérieure, notamment avec Ubuntu 24.04 et Debian 13 :

echo -n 'sk-example-value' > /tmp/plain.txt
sudo systemd-creds encrypt --name=api_key /tmp/plain.txt /etc/credstore/api_key.cred
shred -u /tmp/plain.txt
sudo systemd-run -P --wait -p LoadCredentialEncrypted=api_key:/etc/credstore/api_key.cred \
  systemd-creds cat api_key

La dernière commande affiche sk-example-value. Cela confirme que le fichier chiffré peut être déchiffré sur cet hôte. Référencez-le ensuite dans l’unité :

[Service]
User=agent-review
LoadCredentialEncrypted=api_key:/etc/credstore/api_key.cred
Environment=AGENT_KEY_FILE=%d/api_key
ExecStart=/usr/local/bin/agent-worker

Votre code d’agent ouvre le fichier à l’emplacement $AGENT_KEY_FILE lorsqu’il a besoin de la valeur. La lecture d’un fichier ne dure qu’un instant. Une variable d’environnement reste présente pendant toute la durée de vie du processus, dans chacun des processus enfants qu’il lance.

Privilégiez les tokens à courte durée de validité aux clés à longue durée de validité

Une clé qui n’expire jamais reste valide lorsqu’elle réapparaît, des mois plus tard, dans un journal ou une transcription. Lorsque le service propose un token de session, utilisez-le et définissez la durée de validité la plus courte compatible avec la tâche.

aws sts assume-role \
  --role-arn arn:aws:iam::123456789012:role/agent-readonly \
  --role-session-name agent-review \
  --duration-seconds 900

Quinze minutes est la durée minimale acceptée par AWS STS (security token service) et elle suffit généralement pour une tâche d’agent. Pour GitHub, attribuez à l’utilisateur de l’agent son propre identifiant gh avec un token à granularité fine limité au seul dépôt sur lequel il travaille, afin que gh auth token exécuté pendant cette session ne puisse rien modifier ailleurs. Limitez d’abord l’accès par ressource, puis par durée.

Vérifiez, puis continuez à vérifier

Trois contrôles doivent être effectués après toute modification de la configuration d’un agent. Exécutez-les avec l’utilisateur de l’agent, et non avec votre propre compte.

sudo -u agent-review env | grep -iE 'key|token|secret'
sudo -u agent-review ls -la /home/you/ 2>&1 | head -3
sudo -u agent-review curl -s -o /dev/null -w '%{http_code}\n' --max-time 5 https://api.github.com/user

La première commande ne doit rien afficher. La deuxième doit afficher ls: cannot open directory '/home/you/': Permission denied. La troisième indique quelle identité le chemin réseau de l’agent présente. C’est précisément la question à laquelle répond le modèle de passerelle : un 401 signifie que l’agent ne transmet aucun identifiant GitHub qui lui est propre, tandis qu’un 200 signifie qu’il en transmet un. Vous devez donc savoir de quel token il s’agit. Si vous exécutez des agents sans surveillance, la page contrôler les coûts des agents IA sur un VPS présente les limites budgétaires associées à ces limites d’accès.

FAQ

Puis-je simplement faire confiance au modèle pour qu’il ne divulgue pas mes clés ?

Non, car le modèle n’est pas l’attaquant dans ce modèle de menace. L’agent lit du texte sur des pages web, dans des dépôts et dans des issue trackers. Ce texte peut contenir des instructions. Le modèle ne dispose d’aucun moyen fiable pour distinguer vos instructions du texte qu’il a récupéré. Tout contrôle qui dépend d’une décision correcte du modèle échoue dès qu’une instruction injectée est suffisamment convaincante. Le contrôle doit donc être assuré par le système d’exploitation ou le réseau.

Les variables d’environnement sont-elles vraiment si mauvaises pour les secrets d’un agent ?

Elles posent un problème précis : elles sont héritées. Chaque processus enfant lancé par l’agent en reçoit une copie, notamment un script de build, un test runner et tout hook d’installation de package. Les variables sont également lisibles via /proc/<pid>/environ par le même utilisateur. Tout ce que l’agent lance peut donc les lire sans que l’agent les transmette explicitement. La lecture d’un fichier au moment de l’utilisation, avec LoadCredential= ou via une gateway, limite l’exposition à ce moment précis.

Mettre les secrets dans un vault suffit-il à résoudre le problème ?

Seulement en partie. Un vault règle le problème du stockage. Si vous hébergez vous-même ce vault, il doit faire l’objet de son propre renforcement, car un serveur Vaultwarden est généralement compromis via son admin token ou son fichier de sauvegarde, et non via les éléments chiffrés qu’il contient. Cela ne règle pas la dernière étape : un composant récupère le secret dans le vault et le transmet à l’agent sous forme de variable d’environnement. Vous revenez alors au problème initial. Ce qui compte, c’est le composant qui effectue la substitution. Si l’agent récupère le secret, il détient le secret. Si une gateway ou le système d’init effectue la substitution en dehors du processus de l’agent, l’agent ne détient jamais le secret.

Comment savoir si un agent a déjà divulgué quelque chose ?

En général, vous ne pouvez pas le savoir après coup. C’est précisément l’argument en faveur de la gateway. Sans gateway, les éléments disponibles sont dispersés entre l’historique du shell, la transcription de l’agent et les journaux des connexions sortantes, que vous ne conservez probablement pas. Avec une credential gateway, chaque utilisation d’un credential correspond à une ligne contenant l’identité de l’agent et un timestamp. Si vous soupçonnez une fuite, faites d’abord une rotation de la clé, puis enquêtez. La rotation coûte peu. La certitude, elle, est difficile à obtenir.

Que dois-je faire au minimum aujourd’hui ?

Déplacez chaque fichier .env hors des répertoires dans lesquels vos agents travaillent et créez un utilisateur non privilégié par agent. Ces deux changements prennent environ dix minutes et ferment le chemin d’attaque le plus courant : un agent lit un fichier de credential qui n’avait aucune raison de se trouver à côté du code. La gateway et les tokens à durée de vie courte viennent ensuite, et non en premier. Ce point de départ s’applique à tout runtime d’agent, notamment pour exécuter un agent autonome en toute sécurité sur un VPS.