Le sandbox qui détenait la clé
Le 18 mai 2026, Lasso Security a divulgué deux attaques contre NemoClaw de Nvidia — le sandbox qui fait tourner l'agent de codage autonome OpenClaw. Le sandbox fonctionnait exactement comme Nvidia l'avait annoncé. L'agent à l'intérieur du sandbox a quand même poussé le token GitHub de l'utilisateur vers une pull request contrôlée par l'attaquant, encodé en emojis pour échapper au scanner statique de secrets de GitHub. La question intéressante n'est pas de savoir si le sandbox est cassé. C'est de savoir si un sandbox contenant un fichier de credentials en clair en son sein a jamais été un sandbox au sens architecturalement utile, et ce que la réponse implique pour quiconque livre un agent de codage en 2026.
Deux choses peuvent être simultanément vraies. La première, c'est
que le sandbox NemoClaw de Nvidia, qui enveloppe l'agent de codage
autonome OpenClaw dans un cluster K3s à l'intérieur d'un conteneur
Docker privilégié, fonctionnait exactement comme Nvidia l'avait
documenté. La seconde, c'est que, le 18 mai, Lasso Security a
publié un writeup dans lequel un script postinstall npm
malveillant — tournant à l'intérieur de ce sandbox, ne faisant
que des choses que le sandbox était configuré pour permettre — a
lu le token GitHub de l'utilisateur dans un fichier de config en
clair, l'a encodé en emojis pour défaire le scanner de secrets de
GitHub, et a poussé le résultat vers une pull request contrôlée
par l'attaquant via le binaire gh même que la politique d'egress
avait eu la gentillesse de mettre en liste blanche. Nvidia a
répondu que cela tombait hors du périmètre du bug bounty, au
motif que le sandbox s'est comporté exactement comme il était
configuré pour le faire. C'est, d'une manière que la plupart des
gens du métier de la sécurité trouveront familière, à la fois
correct et à côté de la question.
Voici l'histoire en trois phrases. Le 18 mai 2026, Lasso Security a
publié
une chaîne d'attaque contre NemoClaw, le sandbox de Nvidia pour
faire tourner OpenClaw — un agent de codage autonome qui, comme
Claude Code ou l'agent de Cursor ou Codex CLI, est autorisé à
exécuter npm install, gh pr create et git push pour le compte
de l'utilisateur. La chaîne a deux moitiés : une moitié
d'exfiltration de credentials, dans laquelle un package malveillant
a lu /sandbox/.openclaw/openclaw.json (un fichier en clair
contenant le token GitHub de l'utilisateur aux côtés de clés pour
les services Anthropic, OpenAI, Gemini et Nvidia), a réécrit le
token comme une séquence d'emojis en utilisant une table de
correspondance construite à l'exécution, et a poussé la charge utile
encodée vers une PR publique à travers le binaire gh en liste
blanche ; et une moitié de persistance, dans laquelle une injection
de prompt plantée dans un fichier source de routine a induit
l'agent à réécrire son propre SOUL.md — le fichier de mémoire
comportementale d'OpenClaw — avec une backdoor qui survit à chaque
session suivante.
BDTechTalks
a couvert la divulgation le même jour ; la réponse de Nvidia, citée
dans les deux writeups, était que le sandbox s'est comporté
exactement comme il était configuré pour le faire et que les
scénarios tombent hors du périmètre du programme.
La réponse de Nvidia est, dans un sens technique étroit, vraie. Le
sandbox est un sandbox. Le pod K3s est un pod K3s. La politique
d'egress, qui permet à gh de parler à github.com, est une
politique qui permet à gh de parler à github.com. Rien n'a
échappé à ses bornes de capacités. Rien n'a escaladé. Le conteneur
n'a pas été cassé. Du point de vue du runtime, chaque octet qui
est sorti l'a fait via un binaire que l'utilisateur avait accepté
de laisser sortir, vers une destination que l'utilisateur avait
accepté qu'il atteigne.
C'est juste que l'octet qui est sorti était le token GitHub de l'utilisateur, épelé avec des têtes de dessins animés.
La partie ennuyeuse de la chaîne.
Parcourons la moitié credentials lentement, parce que la mécanique
est tout l'argument. L'agent reçoit une tâche — quelque chose de
peu remarquable, « configure ce nouveau projet à partir d'un README
GitHub » — et le README contient, quelque part dans ses instructions,
une étape qui revient à npm install some-helpful-package. Le
package est malveillant, mais de la même manière discrète dont une
centaine de packages npm par semaine sont maintenant malveillants :
c'est un typosquat ou une dépendance transitive d'un package
récemment compromis, et il livre un script postinstall. Le script
postinstall fait trois choses qui sont individuellement permises et
collectivement catastrophiques.
Il lit /sandbox/.openclaw/openclaw.json. Ce fichier est sur le
système de fichiers du sandbox ; le script tourne à l'intérieur du
sandbox ; personne n'a dit au système de fichiers de ne pas être
lisible, parce que comment l'agent lui-même utiliserait-il le token
GitHub s'il ne pouvait pas lire le fichier où le token GitHub
réside ? Il extrait la valeur ghp_….
Il charge un emoji_map.json livré à l'intérieur du package
malveillant, qui mappe chaque caractère alphanumérique à un emoji —
un fichier JSON parfaitement ordinaire, complètement inoffensif au
scan statique, le genre de chose qu'un formateur markdown ou un
client de chat pourrait légitimement livrer. Le script parcourt le
token caractère par caractère et produit une chaîne comme
🍕🍔🌮🍟…, un emoji par caractère.
Il exécute gh pr create contre un repository contrôlé par
l'attaquant avec la chaîne d'emojis comme corps de PR. Du point de
vue de la politique d'egress, c'est gh qui parle à github.com,
ce qui est la seule chose en liste blanche que gh est autorisé à
faire. La PR est créée. Du côté de l'attaquant, un script lit le
corps de la PR, inverse la table, et reconstruit ghp_…. Le
scanner de secrets de GitHub voit le corps de la PR aussi, mais le
scanner de secrets de GitHub cherche ghp_[A-Za-z0-9]{36}, pas
🍕🍔🌮🍟.
La chercheuse de Lasso Noy Pearl, citée dans la divulgation, l'a
exprimé clairement : « L'encodage en emojis était la technique que
nous avons choisie pour contourner les scans statiques de GitHub »
et « tant que l'agent a une connexion au monde extérieur, aucun
mécanisme statique ne peut vous protéger entièrement. » C'est la
partie où vous hochez la tête et dites oui, évidemment, vous ne
pouvez pas mettre en liste blanche un protocole capable de
transporter des octets arbitraires et puis être surpris quand des
octets arbitraires y passent. Une liste blanche L7 qui permet gh
est une liste blanche L7 qui permet n'importe quoi que vous pouvez
sérialiser dans un corps de PR, ce qui est n'importe quoi.
La moitié persistance — SOUL.md — est mécaniquement différente
mais philosophiquement la même. OpenClaw, selon le writeup de
Lasso, conserve un fichier de mémoire comportementale appelé
SOUL.md que l'agent lit au début de chaque session : règles,
instructions système, contexte accumulé sur les préférences de
l'utilisateur. L'agent peut aussi écrire ce fichier, parce que
toute la prémisse de la mémoire à long terme est que l'agent
devrait pouvoir mettre à jour ses propres croyances. Une injection
de prompt plantée dans un fichier source d'apparence parfaitement
normale que l'agent traite pendant une tâche de routine — l'exemple
de Lasso est un fichier texte qui contient juste des instructions
formulées de la manière dont les données d'entraînement sont
formulées — amène l'agent à ajouter une règle backdoor à SOUL.md.
Les sessions suivantes chargent SOUL.md. La backdoor est
maintenant, dans la propre description de l'agent sur lui-même,
les préférences de l'agent. La formulation de Pearl sur la défense
« s'est comporté comme configuré » de Nvidia est la plus tranchante :
« "Le sandbox s'est comporté comme configuré" est un bon argument
quand la chose qui tourne dedans est un programme déterministe. Il
ne survit pas au contact d'agents pilotés par LLM, dont le
comportement est façonné à l'exécution par chaque morceau de texte
qu'ils ingèrent. »
Un token dans un fichier est un token dans un fichier.
La phrase architecturale que je veux écrire ici, avant d'en arriver à ce que Bromure fait à propos de tout cela, est celle-ci : un secret à longue durée de vie qui vit en tant que fichier en clair à l'intérieur du même rayon d'explosion que le code que l'agent exécute est, du point de vue de tout adversaire capable d'exécuter du code dans ce rayon d'explosion, équivalent à un secret public. Le sandbox ne change rien à cela. Le pod K3s ne change rien à cela. La liste blanche egress ne change rien à cela, parce que la liste blanche egress est autorisée à parler à GitHub, et parler à GitHub — par conception, par intention de l'utilisateur, par toute la raison d'être de l'agent — est le même canal que le package malveillant utilisera.
Il existe un fix bien compris pour cela, et il précède les agents IA de plusieurs décennies, et l'industrie de la sécurité l'utilise discrètement depuis les années 1990. Le fix consiste à mettre le secret de l'autre côté d'une frontière de processus et à courtier son usage, jamais sa valeur.
L'exemple canonique, c'est ssh-agent. Votre clé privée SSH vit
dans une région mémoire détenue par le processus ssh-agent. Quand
ssh a besoin de s'authentifier, il ne dit pas « donne-moi la clé » ;
il envoie les octets du challenge sur un Unix domain socket et
récupère une signature. La clé ne traverse jamais le socket. Un
binaire malveillant tournant sous le même utilisateur peut demander
à ssh-agent de signer des choses, bien sûr — c'est tout l'intérêt
de l'agent — mais il ne peut pas lire la clé, ne peut pas la
copier, ne peut pas l'exfiltrer, ne peut pas l'envoyer chez lui par
mail. Quand la session se termine, la clé meurt avec le processus.
WebAuthn fait structurellement la même chose pour les navigateurs :
la clé privée vit dans le TPM ou la Secure Enclave, la page demande
au navigateur de signer un challenge, la page ne voit jamais la
clé. La migration de l'industrie sur une décennie loin des
mots-de-passe-dans-localStorage est, quand on plisse les yeux, la
même migration que NemoClaw doit faire. Juste un étage plus haut.
Et ça marche pour GitHub aussi. La CLI gh livre un credential
helper qui, sur macOS, peut stocker le token dans le Keychain plutôt
que dans un fichier de config en clair. Plus utilement pour le cas
du sandbox, les GitHub Apps émettent des installation tokens qui
sont à courte durée de vie (typiquement une heure), scopés à des
repositories spécifiques, et révocables ; un proxy de signature
tournant hors du sandbox peut en frapper un à la demande,
l'attacher à une requête que l'agent a générée, et forwarder le
résultat. Le sandbox voit une réponse HTTP générique. Le sandbox ne
voit pas le token. Un script postinstall malveillant demandant à
lire le token depuis l'endpoint courtisé récupère, au mieux, un
token d'une heure scopé à un repo — assez pour faire ce que l'agent
faisait effectivement pour le compte de l'utilisateur, pas assez
pour valoir la peine d'être exfiltré.
Le schéma a un nom dans chaque domaine qui l'utilise — ssh-agent, WebAuthn, signature adossée à un HSM, credential helper de gh, AWS IAM Roles Anywhere — et la propriété sous-jacente est toujours la même : le consommateur du credential est un processus différent du détenteur du credential, et ils communiquent sur un canal plus étroit que « lis les octets ». C'est la différence entre « l'agent peut s'authentifier à GitHub » et « l'agent peut lire le token GitHub ». Un sandbox qui se trompe sur ce point est un sandbox qui a mis la clé de la porte d'entrée du même côté de la porte que les gens qui vous inquiétaient.
C'est, sans ambiguïté, ce que fait Bromure pour la VM par profil
qui fait tourner votre agent de codage. L'agent à l'intérieur de
la VM s'authentifie à GitHub en parlant à un courtier de credentials
sur l'hôte macOS sur un Unix domain socket forwardé ; le token
GitHub (ou, mieux, la clé privée GitHub App qui frappe des tokens
scopés à courte durée) vit du côté hôte de l'hyperviseur, dans le
Keychain macOS, où la VM ne peut pas le voir. L'agent ne lit
jamais la valeur du secret, il ne l'utilise qu'à travers le proxy.
Un script postinstall qui exécute
cat /sandbox/.openclaw/openclaw.json ne trouve rien ; un qui
exécute env | grep TOKEN ne trouve rien ; un qui demande au
courtier « donne-moi le token s'il te plaît » découvre que le
vocabulaire RPC du courtier n'inclut pas ce verbe. La même posture,
appliquée à l'agent GitHub de la même manière qu'elle l'a été à
SSH depuis trente ans.
Une suggestion polie n'est pas un périmètre.
Le truc de l'emoji de Lasso est, dans un sens profond, un
commentaire sur les listes blanches. La politique d'egress
permettait à gh de parler à github.com. L'hypothèse implicite
était que les choses que gh ferait à github.com seraient des
choses qu'un développeur raisonnable voudrait faire — cloner,
pousser, ouvrir des PR, commenter des issues. Mais
gh pr create --body "$ANYTHING" est, par construction, une
primitive qui transporte des octets arbitraires vers une destination
lisible publiquement. Vous ne pouvez pas mettre en liste blanche
cette primitive et empêcher en même temps des octets arbitraires
d'y passer. La liste blanche fait ce qu'elle a dit. Elle ne fait
juste pas ce que vous pensiez qu'elle disait.
C'est la partie du writeup de Lasso qui devrait faire s'asseoir quiconque fait tourner un agent en production. Une liste blanche L7 qui permet un protocole capable de transporter des octets arbitraires n'est pas un périmètre. C'est une suggestion polie pour que les octets à l'intérieur du protocole soient les octets que vous aviez en tête. Que les octets soient dans un corps de PR, dans un message de commit, dans un commentaire d'issue, dans un blob git-LFS, dans les métadonnées d'un tarball uploadé comme asset de release — le protocole est la fuite. Il n'existe pas de filtre statique qui « comprend » la différence entre une PR légitimement riche en emojis (« notre équipe utilise 🍰 pour signifier release ») et un token GitHub encodé en emojis, parce que la différence est sémantique et le filtre est syntaxique.
Alors qu'est-ce qui détecterait cela ? La réponse honnête, c'est qu'aucun truc unique ne le fait ; la structure qui le fait est une combinaison, et chaque pièce est sans intérêt par elle-même.
La première pièce, ce sont les budgets d'octets d'egress par session. Une session dont le brief est « corriger une typo dans README.md » ne devrait pas pousser 14 kilo-octets de blob binaire vers un corps de PR, jamais, pour quelque raison que ce soit. Vous n'avez pas besoin de savoir ce que sont les octets ; vous avez besoin de savoir ce que la session était censée livrer. La discordance de forme entre brief et egress est calculable, mais seulement si quelque chose en dehors de l'agent garde trace du brief et de l'egress au même endroit. L'auto-rapport de l'agent ne fera pas l'affaire ; l'agent est la chose sous suspicion.
La deuxième, c'est la détection d'anomalie de forme de contenu sur les opérations git sortantes. Une PR dont le corps est à 95 % d'emojis, ou à 95 % de base64, ou à 95 % d'hex, dans un repository dont l'historique contient zéro PR de ce genre, est un drapeau. Ce n'est pas une preuve ; c'est un drapeau. Le bon endroit pour calculer ce drapeau est le proxy egress, qui voit la requête sortante avant qu'elle ne quitte l'hôte. Le proxy au niveau hyperviseur de Bromure est l'endroit qui peut le calculer sans faire confiance à l'invité, parce que l'invité est exactement la chose sous suspicion.
La troisième, ce sont les diffs de fin de session entre ce qui
est sorti de la boîte et ce que la session était censée produire.
À la fin d'une session, la VM a produit un ensemble de requêtes
HTTP sortantes, un ensemble d'écritures de fichiers dans le projet
monté, un ensemble de commits git. Si le brief de la session était
« corriger une typo », et que les requêtes sortantes incluent
POST /repos/attacker-handle/random-repo/pulls, c'est un diff
qu'on peut montrer à un humain en deux lignes. Pas nécessairement
bloqué — parfois les agents ont vraiment besoin de faire des choses
surprenantes — mais montré. Le défaut actuel en 2026, à travers
la plupart des produits d'agent de codage, est « trust me bro, it
worked », et l'utilisateur n'a aucun artefact à inspecter même
s'il le voulait.
Le pipeline d'audit est l'artefact.
C'est la partie où il vaut la peine de dire à voix haute ce que
Bromure Enterprise livre vraiment, parce que l'alternative — se
fier aux propres logs de l'agent — est ce qui a mis NemoClaw dans
cette position au départ. Les logs de l'agent sont écrits par
l'agent. Si l'agent a été instruit par un SOUL.md empoisonné de
mentir sur ce qu'il a fait, les logs de l'agent mentiront sur ce
qu'il a fait. Il y a exactement un endroit qui peut produire un
enregistrement véridique de ce qu'un agent a fait, et c'est la
couche en dessous de l'agent.
Bromure Enterprise enregistre, du côté hôte de l'hyperviseur, « la session complète — appels d'outils, commandes shell, éditions de fichiers, codes de sortie » en JSON Lines. Le tracing est activé par défaut ; les ingénieurs n'ont pas à opter-in ; l'agent à l'intérieur de la VM est un Claude Code, un Codex ou un Cursor non modifié. Le flux est « capturé hors de la VM dans un flux JSON Lines résistant à la falsification et livré au sink de logs que vous alimentez déjà (SIEM, data lake, archive de rétention). » Une dépendance compromise à l'intérieur de la VM ne peut pas le nettoyer, parce que les écritures se font de l'autre côté de la frontière de l'hyperviseur que la dépendance ne peut pas franchir.
Les conséquences intéressantes :
- « Cette session a-t-elle poussé vers un repo qui n'était pas le repo de l'utilisateur » est un grep. Pas un grep métaphorique. Un littéral grep contre les JSON Lines d'hier.
- « Cette session a-t-elle ouvert une PR avec un corps qui ne ressemble pas à de la prose » est une regex contre la payload d'appel d'outil capturée.
- « Est-ce que quelque chose a modifié
SOUL.md» est une requête sur les événements d'édition de fichier. Si un scriptpostinstalla réécrit le fichier d'identité de l'agent, ce fait vit dans la trace que l'agent lui-même l'ait jamais mentionné ou non. - Replay. Les traces s'attachent à une pull request. Le reviewer lit le diff et la séquence de prompts, d'appels d'outils et de commandes shell qui ont produit le diff. Ou, dans le langage de la page produit de Bromure : « rejouez le jour où le modèle a décidé de supprimer le dossier migrations ». Le replay forensique est la partie de cette histoire qui n'existe nulle part ailleurs, parce qu'il nécessite d'avoir capturé les entrées et les sorties et les réponses du modèle dans le même flux — ce que l'agent lui-même ne peut produire sans d'abord qu'on lui fasse confiance pour ne pas mentir.
Rien de tout cela n'attrape un attaquant déterminé qui modèle l'exfil pour qu'elle ressemble à de la prose ; il n'y a pas de périmètre contre un adversaire prêt à dépenser des octets en déguisement. Ce que cela attrape, c'est tous les attaquants qui ne l'ont pas fait, ce qui est la majorité d'entre eux, et cela produit l'enregistrement forensique qui transforme le prochain incident de « nous n'avons aucune idée de ce que l'agent a fait » en « nous avons la ligne 14 332 de la trace de session d'hier ». Le défaut 2026 de « l'agent a dit que ça a marché » est l'équivalent de faire tourner de la prod sur un serveur sans logs.
Et l'injection de prompt à l'intérieur de la session ?
Il vaut la peine d'être clair sur ce que l'isolation par VM ne règle pas, parce que les gens les plus susceptibles de lire ce post sont les mêmes gens les plus susceptibles de se faire dire, par quelqu'un qui vend le produit opposé, que les VM sont une panacée. Elles ne le sont pas.
La backdoor SOUL.md — et toute injection de prompt qui prend effet pendant une session — tourne à l'intérieur de la VM, avec quelque soit le scope que l'utilisateur a accordé à l'agent. Si l'utilisateur a dit à l'agent « crée une PR dans ce repo », l'injection de prompt peut créer une PR dans ce repo. Si l'agent a un accès en écriture au dossier du projet, l'injection de prompt peut écrire une backdoor dans le dossier du projet. La VM ne review pas le diff. Ce que la VM fait, c'est garder le diff et sa provenance à un endroit où quelqu'un peut le review plus tard, ce qui s'avère être la partie qui manquait.
Ce que l'isolation par VM plus le courtage de credentials règlent, c'est la partie catastrophique — la partie où un seul mauvais postinstall repart avec un token GitHub permanent, un token npm permanent, vos credentials AWS, et root sur le laptop du développeur. Aucun de ces credentials ne vit à l'intérieur de la VM ; les credentials vivent dans le Keychain de l'hôte et ne sont atteignables qu'à travers un proxy dont le vocabulaire RPC n'inclut pas « donne-moi les octets ». Un token que l'agent peut utiliser à travers un proxy est un token que l'agent ne peut pas exfiltrer, parce que l'exfiltration nécessite d'avoir les octets à envoyer.
La capacité résiduelle de l'attaquant à l'intérieur d'un équivalent
OpenClaw hébergé chez Bromure — ce qu'il peut faire une fois qu'il
a injecté un prompt dans l'agent — c'est de faire faire à l'agent,
dans le scope autorisé de la session, quelque chose que l'utilisateur
n'avait pas l'intention. Ouvrir une PR avec un titre étrange.
Réécrire SOUL.md dans le projet. Ajouter un postinstall à lui.
Tous ces événements sont observables : chaque édition de fichier
atterrit dans le flux d'audit JSON Lines, chaque requête sortante
atterrit dans le proxy egress, chaque prompt et appel d'outil est
enregistré hors de l'agent. On ne demande pas à la VM
d'empêcher l'agent injecté par un prompt de causer du dommage
en-scope — on lui demande de rendre ce dommage visible et borné à
la session, pour que l'hôte reste propre et que l'utilisateur ait
une trace à lire. La persistance à l'intérieur de la VM est
toujours possible ; la persistance à l'intérieur de la VM que
personne ne peut voir ne l'est pas, ce qui est une distinction
significative.
Couplé au courtage de credentials, le pire cas pour l'attaque sur un agent hébergé chez Bromure ressemble à ceci : l'agent livre une mauvaise PR, dans le repo pour lequel il était déjà autorisé, en utilisant un installation token à courte durée, et chaque étape apparaît dans un log résistant à la falsification sur l'hôte. Ce n'est pas zéro dommage. C'est très loin de « l'attaquant a mon token GitHub permanent, exfiltré en emoji, plus une backdoor persistante dans le fichier comportemental de l'agent, plus aucun enregistrement que quoi que ce soit de tout cela s'est passé ».
Ce qui est réellement structurel ici.
Si vous lisez le writeup de Lasso et la réponse de Nvidia en séquence, le désaccord ne porte pas vraiment sur la question de savoir si NemoClaw a un bug digne d'un CVE. Nvidia a raison que le sandbox a fait ce pour quoi il était configuré. Lasso a raison que ce pour quoi il était configuré est insuffisant. Le désaccord porte sur l'endroit où appartient la frontière de confiance.
Nvidia, dans la réponse que Pearl cite, trace la frontière à « la
politique configurée ». À l'intérieur de la politique, tout est
permis ; à l'extérieur de la politique, le client se débrouille
seul. C'est une position normale de responsabilité partagée pour
un fournisseur d'infrastructure. Ce n'est cependant pas une défense
contre le mode de défaillance que Lasso a démontré, parce que le
mode de défaillance est à l'intérieur de la politique. La
politique permet gh. gh peut transporter le token. La politique
est auto-cohérente et inadéquate en même temps.
L'alternative structurelle — la position pour laquelle les posts sur le codage agentique de ce blog plaident dans des termes différents depuis six mois — est de tracer la frontière au credential et à l'observation, pas au binaire et à la destination. Le courtage dit que le credential n'entre jamais dans le sandbox. Le pipeline d'audit au niveau hyperviseur dit que quoi que l'agent fasse à l'intérieur du sandbox est capturé par quelque chose dans quoi l'agent ne peut pas écrire et qu'il ne peut pas éteindre. Ensemble, ils font un sandbox où le pire qu'un postinstall malveillant peut faire est le pire que l'agent était autorisé à faire, sur le repo qu'il touchait déjà, avec des credentials qu'il ne peut pas exfiltrer parce qu'il ne les a jamais eus, et avec chaque frappe d'évidence assise dans votre SIEM.
Les gens de Nvidia n'ont pas tort. L'architecture d'OpenClaw est l'architecture de chaque agent de codage livré cette année, et cela inclut les agents de codage qui ne tournent pas à l'intérieur d'un sandbox du tout. Ce que Lasso a trouvé dans NemoClaw est, structurellement, ce que Wiz et Snyk et Socket trouvent un mardi sur deux dans Cursor et Windsurf et le mode YOLO de GitHub Copilot. La classe de problème, c'est « des credentials en clair à longue durée de vie accessibles à tout ce que l'agent exécute, sans aucun enregistrement de ce que l'agent en a fait », et la classe de fix, c'est « courtisez le credential, observez la session, gardez les reçus ».
Une dernière chose.
Il y a une version de ce post où la leçon est « ne faites pas confiance aux sandboxes ». Cette version est fausse. Les sandboxes, c'est super. Il y a une version où la leçon est « les agents IA sont trop dangereux à déployer ». Cette version est, en pratique, hors de propos — ils sont déployés, la question est comment. La version qui tient debout est celle où le sandbox cesse de se voir demander de faire un travail que le sandbox, par construction, ne peut pas faire.
Un sandbox ne peut pas cacher un credential à un processus qui tourne dedans. Un sandbox ne peut pas faire la différence entre un corps de PR en emojis et un token encodé en emojis. Un sandbox ne peut pas transformer un long protocole en liste blanche en un court. Ce qu'un sandbox peut faire, c'est garder les credentials ailleurs, garder l'agent à un endroit où l'hyperviseur voit chacun de ses mouvements, et écrire cet enregistrement vers un sink que l'agent ne peut pas atteindre. C'est la configuration où le même package npm malveillant, dans le même genre de script postinstall, trouve un système de fichiers vide, un socket de credentials dont le seul verbe est « signe cette chose pour moi, brièvement », et un hyperviseur de l'autre côté du mur qui a noté toute la conversation.
Bromure Agentic Coding est la configuration où c'est le défaut. C'est gratuit, open-source, et livré aujourd'hui. Le prochain emoji est déjà en cours d'upload.