À l'encre invisible
Socket a découvert TrapDoor, une campagne d'attaque de chaîne d'approvisionnement sur npm, PyPI et Crates.io qui fait quelque chose d'inédit : un paquet installé réécrit le fichier de règles de votre agent de code — CLAUDE.md, .cursorrules — et cache l'instruction dans de l'Unicode de largeur nulle que vous ne pouvez pas voir. La prochaine fois que vous lancez l'agent, il lit ses propres règles internes et exécute un « scan de sécurité » qui récolte vos clés SSH, vos identifiants cloud, votre jeton GitHub et vos portefeuilles crypto. L'instruction est invisible ; le vol est réel. Bromure Agentic Coding tend à ce scan une boîte où il n'y a rien à prendre.
Un paquet que vous avez installé modifie le fichier auquel votre agent de code fait le plus confiance — son propre fichier de règles — et écrit la ligne malveillante dans des caractères qui s'affichent comme rien. Vous relisez le fichier, vous voyez d'ordinaires notes de projet, et vous approuvez. L'agent lit le même fichier et y voit un ordre : lancer un scan de sécurité, envoyer les résultats ici.
La plupart des attaques que nous couvrons cachent une instruction malveillante là où l'agent la lira — une page web, un commentaire de pull request, un README. Celle-ci la cache au dernier endroit où vous penseriez à regarder : la configuration même de l'agent. Le 22 mai 2026, Socket a commencé à suivre une campagne baptisée TrapDoor — 34 paquets malveillants et plus de 384 versions publiés sur npm, PyPI et Crates.io, les opérateurs republiant plus vite que les retraits ne pouvaient suivre. Le flux automatisé de Socket repérait les nouvelles versions en cinq minutes et cinquante-six secondes en moyenne ; la plus rapide, cinquante-huit secondes après publication. The Hacker News et Phoenix Security l'ont couvert la même semaine. Nous en parlons maintenant parce que son dernier coup est l'exemple le plus net à ce jour d'un voleur de chaîne d'approvisionnement conçu pour viser droit sur un agent de code.
Les paquets ressemblent aux outils qu'un développeur attrape sans
réfléchir : chargeurs d'environnement, vérificateurs de portefeuille,
assistants de build, et — celui par lequel tout a commencé —
eth-security-auditor, un « auditeur de sécurité ». Installez-en un et il
fait les choses ordinaires d'un infostealer. Mais la charge npm partagée,
un fichier de 48 Ko nommé trap-core.js, fait une chose de plus qui n'a
rien d'ordinaire. Elle écrit dans .cursorrules et CLAUDE.md.
La ligne que vous ne pouvez pas voir
Ces deux fichiers sont des règles internes. Cursor lit .cursorrules ;
Claude Code lit CLAUDE.md. Ils existent pour qu'un dépôt puisse dire à
l'agent comment se comporter dans ce projet — les conventions, ce qui se
fait et ne se fait pas — et l'agent les traite comme des instructions
permanentes, appliquées à tout ce qu'il fait dans ce dossier. C'est le
texte le plus fiable de l'espace de travail, parce que vous êtes censé
l'avoir écrit vous-même.
TrapDoor y écrit, et cache l'écriture. L'instruction malveillante est
encodée avec des caractères Unicode de largeur nulle — U+200B,
U+200C, U+200D, U+FEFF — des points de code qu'un éditeur de texte
n'affiche pas du tout. Ouvrez CLAUDE.md et vous voyez vos notes de
projet ordinaires. Lancez git diff et, selon vos réglages, vous pourriez
ne rien voir qui mérite de s'arrêter. Les octets sont là ; les glyphes ne
le sont pas. C'est un message écrit à l'encre invisible, et le seul
lecteur qui la révèle est l'agent, qui analyse tout le flux Unicode et
trouve une instruction posée dans son propre règlement.
Le scan qui vole
L'instruction cachée dit à l'agent de lancer un « scan de sécurité ».
Rien là-dedans ne semble alarmant — vous avez confié à l'agent un auditeur
de sécurité, et voilà que ses règles lui demandent d'auditer. Ce que le
scan fait réellement, c'est parcourir la machine à la recherche de tout ce
qui vaut de l'argent. Le décorticage de la charge par Socket liste les
clés SSH, les identifiants AWS, les jetons GitHub, les profils de
navigateur et bases de connexion, les variables d'environnement et clés
d'API, et — la signature de cette campagne — les portefeuilles de
cryptomonnaie : Sui, Solana, Aptos et les extensions de portefeuille de
navigateur. Puis il exfiltre vers un site GitHub Pages
(ddjidd564[.]github[.]io) et, dans la variante Crates.io, vers des
GitHub Gists.
Un détail montre à quel point c'est délibéré. Avant d'envoyer quoi que ce soit, la charge « appelle activement les API AWS et GitHub pour confirmer si les identifiants volés sont valides, filtrant les jetons de grande valeur avant l'exfiltration ». Elle ne se contente pas de tout attraper et de tout déverser. Elle teste chaque identifiant contre le vrai service, garde ceux qui sont actifs et jette les morts. Les opérateurs veulent une liste nette de clés qui fonctionnent.
Phoenix Security nomme pourquoi cela touche le plus durement les gens visés : les développeurs crypto et DeFi, parce que « les clés SSH, les identifiants cloud, les jetons GitHub et les keystores de portefeuille crypto cohabitent couramment sur la même machine ». Cette phrase, c'est toute la surface d'attaque. L'agent tourne sur votre ordinateur portable, en tant que vous, et tout ce qui a de la valeur est à sa portée. La ligne invisible dans le fichier de règles n'est que le déclencheur ; l'accès ambiant est la charge utile.
Où Bromure trace la ligne
Bromure Agentic Coding ne dépend pas du repérage de la ligne invisible — même si, on y viendra, il lit les mêmes octets. Il change ce que la ligne peut atteindre quand elle se déclenche. L'agent de chaque profil tourne dans une VM Linux jetable sur Apple Silicon, à un hyperviseur de macOS, et les identifiants dans cette boîte ne sont pas les vôtres.
Les identifiants sont des leurres. C'est la couche dans laquelle
TrapDoor fonce tout droit, parce que TrapDoor est, au fond, un voleur
d'identifiants. Un courtier d'identifiants
sur l'hôte garde vos vrais secrets Anthropic, AWS et GitHub entièrement
hors de la boîte. À l'intérieur de la VM, l'agent voit des remplaçants —
un jeton brm_…, un kubeconfig synthétique, une clé SSH jetable — et le
courtier n'insère la vraie valeur qu'à la frontière réseau, sur les
requêtes vers des destinations que vous avez déjà approuvées. Alors le
« scan de sécurité » s'exécute, parcourt le disque et récolte exactement
ce pour quoi il a été envoyé : des faux. Et la petite étape de validation
astucieuse de la campagne se retourne contre elle — elle appelle AWS et
GitHub pour confirmer que les jetons sont actifs, les leurres échouent à
ce test, et le filtre censé ne garder que les clés qui fonctionnent ne
garde rien.
Les portefeuilles ne sont pas là. Les keystores Sui et Solana, les bases de connexion du navigateur, les extensions de portefeuille — rien de tout cela ne vit dans une VM de code jetable. C'est sur votre vraie machine, à un hyperviseur de là, où le scan ne peut pas le voir. Fermez la session et la boîte se réinitialise, fichier de règles empoisonné compris.
L'exfiltration est filtrée. Supposons que le scan trouve quelque chose
qui vaut la peine d'être envoyé. Le POST vers ddjidd564.github.io, ou
l'écriture dans un GitHub Gist, est une requête sortante, et toute requête
sortante traverse le proxy hôte, où la vraie destination est vérifiée
contre la liste approuvée du profil au moment de sortir. Un voleur qui
appelle chez lui une adresse que le profil n'a jamais approuvée ne sort
pas — et les formes destructrices contre les API que le profil expose
rencontrent un garde-fou qui peut les refuser, quoi que l'agent ait été
amené à croire.
En amont de tout cela se trouve la couche qui rencontre TrapDoor à son déclencheur. Toute l'attaque commence par du contenu que l'agent lit — le fichier de règles empoisonné — et Bromure évalue le contenu non fiable avec un détecteur d'injection sur l'appareil avant que le modèle n'agisse dessus. L'Unicode de largeur nulle qui cache l'instruction à votre éditeur ne la cache pas à l'évaluateur : il lit le même flux d'octets, points de code invisibles compris, et un fichier de règles qui se décode en « lancer un scan et envoyer les secrets » est exactement la forme qu'il est fait pour signaler. Il en attrape l'essentiel à la porte. Un encodage assez inédit peut encore tromper un classifieur, ce qui est la raison pour laquelle il se tient devant la boîte jetable plutôt qu'à sa place.
Invisible pour vous, vide pour le voleur
La partie déstabilisante de TrapDoor, ce n'est pas l'astuce d'encodage. C'est que l'astuce fonctionne sur le seul fichier auquel on vous a dit de faire confiance — les règles que vous avez écrites pour votre propre agent — et qu'un humain relisant ce fichier ne voit rien d'anormal, parce qu'il n'y a rien à voir. La détection doit gagner à chaque fois contre chaque nouvelle façon de cacher une ligne. C'est une course qui vaut la peine d'être courue, et l'évaluateur sur l'appareil la court, mais ce n'est pas là que la sécurité devrait reposer.
Bromure Agentic Coding la fait reposer un niveau plus bas. Il suppose que l'agent finira par lire une instruction empoisonnée qu'il ne peut pas distinguer d'une vraie — encre invisible ou non — et fait en sorte que, lorsque l'agent part chercher des secrets à voler, les secrets soient des leurres, les portefeuilles soient sur une machine qu'il ne peut pas atteindre, et la sortie soit filtrée. Le scan tourne quand même. Il revient simplement les mains vides. Installez-le et donnez à votre agent un règlement qui, empoisonné ou non, pointe vers rien qui vaille la peine d'être pris.