Trois agents, une seule chose à voler
À Black Hat USA 2026, Novee a cassé la configuration par défaut de Claude Code, Gemini CLI et Codex de trois façons différentes, chacune partant d’une issue GitHub qu’un inconnu anonyme pouvait ouvrir. Les contournements n’avaient rien en commun — un décalage de guillemets, une allowlist shell non appliquée, un AGENTS.md de confiance — mais les trois chaînes se terminaient par la même étape : lire un vrai identifiant dans le processus de l’agent. Bromure Agentic Coding ne durcit pas cette dernière étape. Il vide le processus : l’exfiltration s’exécute et expédie un leurre.
Trois éditeurs, trois bugs de harnais sans lien entre eux, un même geste
final : lire la clé API ou le token présent dans le processus de l’agent et
l’expédier dehors. Dans un profil Bromure, cette valeur est un placeholder
brm_…. L’exfiltration réussit, et l’attaquant reçoit une chaîne qui ne
veut rien dire hors de votre Mac.
À Black Hat USA 2026 cette semaine, Novee a présenté « Trusted Enough to Run: Breaking AI Agents in Official Workflows ». Le chercheur Elad Meged a testé la configuration par défaut de trois agents de code contre les dépôts publics de chaque éditeur, et a cassé les trois. Les comptes rendus sont parus le 6 août.
Le point d’entrée était le même dans chaque cas, et c’est le moins cher qui soit : une issue GitHub ou une pull request ouverte par un inconnu anonyme sans le moindre privilège. L’agent lit ce texte non fiable dans le cadre de son travail, et le harnais — le code autour du modèle qui décide de ce qu’il peut exécuter — échoue à garder ce texte du bon côté de la ligne. Novee a retrouvé les mêmes défauts vulnérables sur plus d’une centaine de dépôts publics au-delà des trois éditeurs testés.
Les trois chemins d’attaque n’ont rien à voir entre eux. Ils se terminent au même endroit, et c’est cette fin commune qu’il faut retenir.
Trois portes différentes, un seul mur du fond
Claude Code
La chaîne enregistrée sous CVE-2026-54316 exploitait deux coutures. La
première était un décalage entre la façon dont Claude Code validait une
commande et celle dont le shell l’interprétait réellement : une chaîne entre
guillemets, anodine pour le validateur, se parsait autrement une fois entre
les mains de bash, et un drapeau git push --receive-pack a traversé
vingt-trois contrôles de sécurité
qui faisaient tous, individuellement, leur travail. La seconde couture était
l’exfiltration. Un tac en lecture seule — la commande qui affiche un
fichier à l’envers — suffisait à lire un secret et à le pousser dehors,
inversé, via les logs GitHub Actions, et une variante faisait fuiter la clé
API caractère par caractère en incrémentant le compteur public de
téléchargements d’un modèle HuggingFace puis en le relisant. Anthropic a
publié des correctifs.
Gemini CLI
Noté CVSS 10.0. En mode headless, Gemini CLI faisait automatiquement
confiance au dossier de travail et chargeait la configuration d’agent qu’il
y trouvait — sans sandbox, sans approbation — si bien qu’une pull request
déposant un fichier de config s’exécutait avant même l’initialisation de la
sandbox. Deux hypothèses du harnais ont cédé : l’allowlist shell
« restreinte » n’était jamais appliquée à l’exécution, et l’assainissement
d’environnement qui purgeait les secrets du processus enfant les laissait
dans le processus parent, lisibles via /proc. Google a livré un
changement cassant du modèle de confiance headless dans 0.39.1 et
0.40.0-preview.3.
Codex
Codex exécute deux passes d’agent sur un espace de travail partagé. .git
et .codex étaient protégés en écriture ; pas AGENTS.md, rechargé comme
instructions de confiance à chaque exécution. La première passe, qui traite
l’entrée non fiable, écrivait un AGENTS.md empoisonné ; la seconde,
« sûre », le chargeait comme autorité et propageait les instructions
malveillantes avec des permissions élevées. OpenAI a séparé les passes en
jobs isolés en trois jours.
La partie qui ne change pas
Le propre résumé de Novee est qu’« aucune de ces failles n’était une simple erreur de configuration : c’étaient des décisions de sécurité correctes qui cédaient aux points de passage ». C’est la bonne lecture côté harnais. Mais regardez où chaque chaîne se termine.
Le tac de Claude lit un identifiant et le compteur HuggingFace fait fuiter
la clé API. La faille /proc de Gemini expose les secrets du processus
parent. La seconde passe élevée de Codex porte les tokens de
l’environnement dans une instruction contrôlée par l’attaquant. Trois
coutures sans lien s’ouvrent de trois façons différentes, et chacune finit
par tendre la main vers le même objet : un vrai secret qui attendait, posé
dans le processus ou l’environnement de l’agent, qu’on le lise.
C’est l’hypothèse que partagent tous ces exploits — si vous obtenez de
l’exécution de code en tant qu’agent, l’identifiant est à portée de main. Il
l’est presque toujours. La ANTHROPIC_API_KEY, le GITHUB_TOKEN, les clés
AWS : la façon ordinaire de lancer un agent de code les met toutes dans
l’environnement du processus, parce que c’est là que les outils s’attendent
à les trouver.
Bromure Agentic Coding n’essaie pas de gagner la course à l’armement du harnais. Il retire ce que le harnais protège.
Là où la chaîne casse
Bromure exécute l’agent de chaque profil dans une VM Linux jetable sur Apple Silicon, et fait passer chaque octet de son trafic réseau par un proxy sur l’hôte, hors de la boîte où tourne l’agent. Vous pouvez faire tourner le même agent autonome de tri d’issues que Novee a attaqué — en l’hébergeant vous-même au lieu de lui confier un runner de workflow. Rejouez les trois chaînes contre cette architecture : chacune se défait, et l’étape de l’identifiant se défait de la même façon pour les trois.
L’identifiant n’est jamais dans le processus
C’est la garantie qui neutralise l’étape finale commune. Les vraies clés
Anthropic, OpenAI et xAI sont injectées dans la VM sous forme de
placeholders brm_… et échangées contre les vraies valeurs seulement au
proxy de l’hôte, sur le fil, pour le seul hôte de destination auquel
chacune appartient. La clé n’est jamais dans la mémoire de la VM, jamais
dans /proc, jamais dans une variable d’environnement lisible par un
processus enfant ou parent, jamais dans un log. tac lit un leurre. Le
compteur HuggingFace fait fuiter un leurre caractère par caractère. Le
scrape de /proc renvoie un leurre. Chaque exfiltration de la conférence
s’exécute jusqu’au bout et expédie une chaîne qui ne se résout que sur un
seul Mac, qui n’est pas la machine où elle a tourné.
Le RCE atterrit dans une boîte effaçable
« Exécution de code sur l’hôte qui fait tourner l’agent » : c’est la formule de l’advisory de Gemini, et cet hôte est la frontière de confiance que Bromure déplace. L’exécution pré-sandbox de Gemini et le contournement shell de Claude obtiennent tous deux une VM Linux jetable, à un hyperviseur de macOS, en NAT, d’où rien de votre réseau n’est joignable. Erase home jette ce que l’exécution a écrit et remet le répertoire home dans son état post-clone. L’exploit qui possède l’agent possède une VM que vous alliez de toute façon jeter.
L’écriture vers main est refusée au proxy
Les deux escalades visent le même trophée : la chaîne de Claude pousse
avec git push --receive-pack, celle de Gemini pousse du code
malveillant dans la branche principale. C’est le versant supply chain —
un checkout compromis devient un paquet empoisonné en aval. Réglez le
garde-fou GitHub sur lecture seule ou blocage destructif et
git-receive-pack est refusé au proxy de l’hôte, où un garde contourné
dans la VM n’a pas voix au chapitre. Les fetchs passent toujours ; le
push qui empoisonnerait la branche, non.
Le fichier d’instructions est noté avant d’être obéi
L’entrée, c’est du texte d’issue et de PR non fiable que le harnais n’a
pas su contenir, et toute la chaîne Codex vit dans un AGENTS.md écrit.
Bromure note le contenu des résultats d’outils que l’agent lit — pages
web, corps d’issues, contenus de fichiers — avec un modèle local de
détection d’injection de prompt, et note les fichiers d’autorité
eux-mêmes (CLAUDE.md, AGENTS.md et leurs variantes) avec un
classifieur dédié plus un scanner de payloads Unicode invisibles.
L’AGENTS.md empoisonné entre les deux passes de Codex est précisément
ce que ce second détecteur est fait pour attraper, et il tourne sur
l’hôte avant que le modèle n’agisse sur le fichier.
Deux de ces réglages sont actifs par défaut, et le broker d’identifiants n’est pas un réglage du tout — c’est la façon dont un profil Bromure détient un secret, tout simplement. Les canaux dérobés complètent le tableau : le log GitHub Actions, le compteur HuggingFace, l’hôte sortant inattendu traversent tous le proxy de l’hôte, et le Security Log et le Trace Inspector enregistrent l’hôte, le statut et le rapport de substitution de chaque requête — le canal auxiliaire qui a fait fuiter un leurre est aussi une ligne sur une liste que vous pouvez lire.
Le harnais continuera de casser
Les trois correctifs provoqués par Novee sont tous bons, et tous étroits. Anthropic a corrigé le décalage de guillemets ; Google a changé le modèle de confiance headless ; OpenAI a séparé les passes. Chacun referme la couture précise qui a été trouvée. Aucun ne change ce que les trois exploits avaient en commun : un identifiant en état de marche posé dans le processus de l’agent, à prendre. Le prochain bug de harnais — et Novee a trouvé les mêmes défauts sur une centaine d’autres dépôts, donc il y en aura un — tendra la main vers lui à nouveau.
Vous pouvez répondre à chaque divulgation par un patch et une revue de configuration, et vous devriez. Mais le patch ferme une porte dans un agent, et la revue se fait dépôt par dépôt, version par version. L’identifiant qu’un exploit fonctionnel vient chercher est le même pour les trois agents et pour chaque bug futur, et c’est la seule chose que vous pouvez mettre hors de portée en une seule décision : gardez le vrai secret sur l’hôte, donnez un placeholder à l’agent, et laissez le proxy produire la vraie valeur uniquement pour l’hôte auquel elle est adressée.
Installez Bromure Agentic Coding, et donnez à l’agent une boîte — et un identifiant — que vous acceptez de perdre.