La commande s'appelait aipoison
Socket a découvert une grappe de 18 paquets npm imitant le scope privé @ali d'Alibaba. Aucune des archives ne contenait de malware. Le RAT s'assemblait à l'installation à partir d'un fichier JSON hébergé dans un dépôt GitHub que l'attaquant contrôle encore, et son plan de persistance incluait de patcher du Python dans les répertoires .skills des outils de code IA, via des commandes nommées aipoison, aipoison_inject et aipoison_deploy. Lire le code ne pouvait pas trouver cela. Bromure Agentic Coding juge ce qui était visible depuis le début : un paquet sans réputation attend votre consentement au proxy hôte, les trois requêtes qui assemblent le payload traversent un fil qui ne parle qu'aux destinations que vous avez approuvées, et chaque fichier écrit par le RAT atterrit dans une VM qui vit le temps d'une tâche.
Quelque part dans le payload final se trouve une commande nommée
aipoison. Son travail : plonger dans le répertoire de skills de votre
outil de code IA et patcher un fichier Python, pour que la prochaine fois
que vous vous mettez au travail, l'attaquant s'y mette aussi.
Le 3 août 2026, The Hacker News
a couvert la recherche que Socket a publiée fin juillet :
une grappe d'environ dix-huit paquets npm, mis en place fin avril, restés
trois mois sur le registre avant que quiconque ne les repère. Ils imitent
les paquets privés d'Alibaba sous le scope @ali en publiant les mêmes
noms sans scope (aone-cloud-cli, def-open-client, open-worker-cli,
uniapi-bridge), de sorte qu'un développeur ou un build au sein de
l'organisation ciblée résout le sosie public et se retrouve avec un cheval
de Troie d'accès distant greffé sur l'arbre de dépendances. Karlo Zanki,
chercheur chez Socket, lit le mobile comme de l'espionnage industriel.
Rien dans les paquets n'était malveillant
Ouvrez n'importe laquelle de ces archives et vous ne trouvez rien à
signaler. Pas de hook postinstall, la première chose que tout le monde
greppe. Les paquets-appâts dépendent de smart-config-manager, qui dépend
de cloud-config-fetcher et de local-config-parser. Un gestionnaire de
config, un fetcher, un parseur : des utilitaires banals, chacun lisible en
une minute.
La malveillance vit dans la composition, et dans un fichier que l'attaquant
n'a jamais livré. À l'import, le fetcher télécharge
defaults/preferences.json depuis un dépôt GitHub que l'attaquant
contrôle, et contrôle toujours, puis l'écrit sur disque sous le nom
.cloud-preferences.json. Le parseur évalue les « règles de
transformation » de ce fichier dans un vm Node, et c'est là que vit
l'attaque. L'une des règles est une évasion de sandbox au statut de
folklore :
var F = items.constructor.constructor; // recover Function
var p = F('return process')(); // recover process
Depuis process, il descend une échelle de repli (getBuiltinModule,
mainModule.require, mainModule.constructor._load) jusqu'à ce que l'une
d'elles livre require sur la version de Node où il a atterri. Puis il
récupère setting.js depuis un bucket de stockage Alibaba Cloud, qui prend
l'empreinte de l'hôte et installe le payload : sous Windows, tuer Alilang,
l'application de sécurité d'Alibaba elle-même, et remplacer son app.asar
par une copie piégée ; sous Linux, déposer un binaire dans /tmp, le
lancer détaché, supprimer le fichier ; sous macOS, s'injecter dans
~/.zshrc et enregistrer un LaunchAgent qui se déclenche toutes les dix
minutes.
GBHackers a mis le design dans son titre : les attaquants ont réparti le RAT entre les paquets pour échapper aux revues de code isolées. L'attaquant a construit cette campagne pour survivre à sa lecture. Relisez chaque paquet isolément : il passe. Relisez l'arbre entier : il passe encore, parce que la partie hostile est un fichier JSON sur un serveur, récupéré après la fin de votre revue, modifiable par l'attaquant entre votre audit et votre installation.
Le plan de persistance inclut votre agent
Socket a récupéré le payload final sous le nom aone-cli. Il fait ce que
font ces choses-là : commandes shell, envoi et téléchargement de fichiers,
reconnaissance de l'hôte, captures d'écran, un proxy TCP inverse chiffré,
et une commande dws_lateral qui se déplace via DingTalk. Son trafic C2
porte des en-têtes Origin et Referer forgés, prétendant venir d'un
domaine de documentation interne d'Alibaba.
Un groupe de commandes fait de cette histoire une histoire d'agents de
code. À côté des verbes habituels, le RAT embarque aipoison,
aipoison_inject et aipoison_deploy. Elles patchent des scripts Python
installés dans les répertoires .skills d'outils de développement précis,
en marquant l'extrait injecté d'un # __INJECT_MARKER__, pour qu'un script
tiré du C2 s'exécute plus tard, depuis l'intérieur de l'outillage, en votre
nom. Parmi les cibles nommées figure
Qoder,
l'IDE agentique d'Alibaba lui-même, qui a dépassé les cinq millions
d'utilisateurs quelques mois après son lancement en août dernier.
Quelqu'un s'est assis, a regardé la machine de développeur moderne, et a
choisi le dossier de skills de l'agent comme point d'ancrage durable : un
répertoire de scripts qui s'exécute avec vos permissions au début de chaque
session, et que presque personne ne diffe jamais. Nous avons déjà vu ce
geste, quand un ver s'est copié dans
.claude pour que le prochain démarrage
d'agent réinfecte la machine. Il est passé du bricolage improvisé d'un ver
à une commande nommée dans une boîte à outils d'espionnage.
Les parties que l'attaquant ne pouvait pas cacher
Lire le code n'allait jamais trouver cela. L'attaque avait pourtant des prérequis, et tous étaient visibles : un paquet sans historique et sans réputation, trois connexions sortantes avant de pouvoir agir (le fichier de règles sur GitHub, l'étape sur le stockage cloud, le C2), et une machine encore là le lendemain.
Bromure Agentic Coding pose une décision sur chacun d'eux, et la prend sur votre Mac, hors de la boîte où tourne l'agent, là où rien à l'intérieur ne peut discuter.
L'installation marque une pause au registre. Chaque récupération de
paquet traverse le proxy côté hôte, qui applique la politique supply chain
de votre espace de travail à la réponse avant qu'un octet n'atteigne la VM.
Activez le filtrage de paquets et le proxy consulte un fournisseur de
réputation pour chaque artefact. L'un des deux fournisseurs sélectionnables
est Socket, dont la recherche fait l'objet de ce billet. Quand aucune
source activée ne peut se porter garante d'un paquet, le proxy retient le
téléchargement et vous demande. Des sosies d'un scope privé, publiés le
trimestre dernier avec une poignée de téléchargements et aucune réputation
nulle part, s'arrêtent là. L'application se fait sur l'hôte à dessein : le
.npmrc à l'intérieur de la VM peut durcir la politique et ne peut pas
l'assouplir, donc la règle tient même quand la chose compromise est celle
qui fait la police.
Le fil refuse l'assemblage. Ce design se brise contre le consentement
de sortie, parce qu'avec rien d'hostile dans l'archive, le réseau est
l'attaque. Le proxy hôte vérifie chacune des trois requêtes (le fichier raw
GitHub de l'attaquant, le bucket qui sert setting.js, l'hôte C2) contre
les destinations que vous avez approuvées pour ce profil. Le registre d'où
vous installez est sur cette liste. Le chemin raw d'un inconnu et un bucket
nommé d'après un CLI dont vous n'avez jamais entendu parler n'y sont pas.
Le proxy n'a aucune opinion sur items.constructor.constructor et n'en a
pas besoin. Il lit la destination, ne trouve rien d'approuvé, et coupe la
connexion. Votre installation se termine, votre build tourne, et le RAT ne
s'assemble jamais, parce que ses pièces ne se retrouvent jamais dans la
même pièce.
La persistance obtient une machine dont la durée de vie est une tâche.
Supposez que toute la chaîne s'exécute quand même, parce que vous avez
approuvé une destination plus large que prévu et que les étapes passent. La
ligne dans ~/.zshrc, le LaunchAgent aux dix minutes, l'app.asar piégé,
le Python .skills patché : tout cela s'écrit dans une VM Linux jetable, à
un hyperviseur de macOS, qui héberge l'espace de travail de cette tâche, et
que vous jetez quand le travail est mergé. aipoison parie que l'outillage
qu'il patche et l'hôte qu'il a compromis sont la même machine à longue
durée de vie. Dans un profil, ce pari est perdant. La reconnaissance qui
s'exécute d'abord revient avec des leurres du
broker : vos vrais identifiants vivent
sur l'hôte et ne sont injectés au fil que pour les destinations approuvées,
donc ils n'ont jamais été dans la
VM pour être collectés.
Relire un artefact vous renseigne sur l'artefact
Les chercheurs redonnent cette leçon chaque semaine dans une bibliothèque différente. Hier, un flag de confiance est tombé parce que la vérification et le chargement se produisaient à deux moments différents. En juin, un dépôt est resté propre parce que le reverse shell vivait dans un enregistrement DNS. Aujourd'hui, dix-huit paquets se lisent propres parce que la partie malveillante est un fichier JSON que l'attaquant tient encore.
Les agents aiguisent le problème, parce qu'ils sont rapides. Un agent à qui l'on demande de câbler une API interne ajoute la dépendance, lance l'installation et passe à l'étape suivante de la tâche le temps que vous changiez de fenêtre. Cette vitesse est la raison même pour laquelle vous l'avez acheté. Placez le jugement là où la vitesse ne peut pas le dépasser : à la récupération sur le registre et au fil, où votre Mac décide contre une politique que vous avez définie une fois, pour chaque paquet et chaque connexion de l'agent.
Continuez à laisser l'agent installer des choses, parce que c'est là qu'est le levier. Installez Bromure Agentic Coding, activez les couches supply chain, et donnez au profil une liste de destinations qui ont du sens pour le travail. La prochaine campagne cachera son payload ailleurs, la seule prédiction sûre dans ce métier, et elle devra quand même le récupérer à travers un fil qui vous demande d'abord.