La commande commençait par npm install
Le 24 août 2026, l'équipe CTRL de Cato Networks a publié l'analyse d'une campagne qui achète des résultats Google sponsorisés sur « codex macos download », dépose les développeurs sur une page Google Sites déguisée en portail Codex d'OpenAI, et leur demande de coller dans le Terminal une commande dont la première ligne est un vrai npm install de Codex. Tout ce qui suit cette ligne est du base64. Bromure Agentic Coding n'envoie jamais personne chercher un agent de codage : la commande d'installation est une chaîne figée dans le catalogue d'images de Bromure, elle s'exécute dans une VM Linux jetable, les identifiants qui s'y trouvent sont des leurres, et avec le trafic sortant non apparié refusé, les trois requêtes du chargeur ne quittent jamais la machine.
Depuis deux ans, l'industrie construit des contrôles pour ce qu'un agent de codage installe. Cette campagne remonte d'un cran et empoisonne la façon dont vous installez l'agent de codage. Cette étape-là n'a ni registre, ni fichier de verrouillage, ni attestation de provenance. Elle a une barre de recherche, une page qui a l'air correcte, et vos propres mains sur le clavier.
Un développeur veut essayer le CLI Codex d'OpenAI sur son Mac, alors il tape
codex macos download dans Google. Le premier résultat est sponsorisé, placé
au-dessus de l'annonce d'OpenAI elle-même. Il mène à un portail de
téléchargement propre, avec le bon logo et la bonne typographie, hébergé sur
sites.google.com. La page dit : ouvrez le Terminal, collez ceci.
Il colle. La commande commence par npm install et le nom du paquet est
correct.
Le 24 août, l'équipe de recherche CTRL de Cato Networks a publié l'analyse de cette campagne, reprise le jour même par Infosecurity Magazine, SiliconANGLE et Techzine. La charge finale est un voleur d'informations pour macOS. C'est la livraison qui vaut l'analyse.
Google hébergeait la page. Quelqu'un d'autre hébergeait le leurre.
Google Sites est un constructeur de sites. N'importe qui avec un compte obtient une page sur un domaine Google, et le certificat, le cadenas et la première moitié de l'URL appartiennent tous à Google. C'est cela, la confiance louée.
La page elle-même ne contient rien. Cato n'y a trouvé aucun code malveillant.
Le leurre arrive dans une iframe pointée vers l'infrastructure de
l'attaquant, routée, selon l'analyse de Cato, par un proxy de contenu statique
de Google, si bien que même le second saut ressemble à Google allant chercher
quelque chose. Techzine nomme deux des hôtes d'iframe : bright-links[.]com et
swiftsaverfin[.]com.
Cette séparation achète deux choses aux opérateurs. La page visible ne change jamais, donc elle ne déclenche aucun système de réputation et n'est jamais réexaminée, et ils échangent les charges de l'autre côté de l'iframe quand bon leur semble. Cato a compté trois jeux d'infrastructure distincts, le troisième réutilisant un hôte d'iframe du premier.
Le reste se lit comme une opération de fraude publicitaire mature. Les leurres
actifs vivent sous un chemin obscurci, /codexx/, tandis que /codex/ sert
quelque chose d'inoffensif. Les opérateurs identifient les visiteurs, et tout ce
qui n'est pas une cible macOS plausible voit du contenu bénin, ce qui est leur
réponse aux chercheurs et aux bacs à sable. Les domaines tournent. Les URL de
charge varient.
La première ligne était vraie
ClickFix ne vous sert pas un fichier. Il vous donne une instruction et vous laisse porter vous-même la charge de l'autre côté de la frontière. Comme le dit Techzine, « aucun fichier n'est téléchargé qu'une solution antivirus pourrait bloquer ».
La commande collée commence par une chaîne npm install d'apparence légitime
pour Codex. C'est là tout le tour de passe-passe. Un développeur sur le point
d'installer un CLI Node voit npm install, voit le nom du paquet qu'il a
cherché, et son cerveau classe la ligne comme correcte. Le blob base64 qui
suit est à un opérateur shell de distance, sur la même ligne, au-delà du pli de
la boîte de copie. On ne lit pas la seconde moitié d'une commande dont la
première moitié est la commande qu'on attendait.
Décodé, il va chercher un script distant et le passe à zsh. Trois étapes
suivent.
L'étape une est un script shell rembourré de code mort et de variables
inutilisées, enveloppant un blob encodé qui finit remis à eval. Le
rembourrage existe pour déjouer la correspondance de motifs et pour faire
abandonner l'humain qui parcourt le fichier.
L'étape deux émet une balise vers l'attaquant avec un paramètre
event=pasted avant de faire quoi que ce soit d'autre. C'est un accusé de
réception. Quelqu'un, à l'autre bout, mesure le taux de collage de ses pages
d'atterrissage, comme un marketeur mesure des conversions.
L'étape trois télécharge le binaire dans /tmp/helper, exécute xattr -c
pour retirer l'attribut de quarantaine que macOS attache à tout ce qui est
arrivé du réseau, ce qui supprime l'avertissement de Gatekeeper, le marque
exécutable, et le lance. Le binaire est un Mach-O universel, il tourne donc
aussi bien sur Intel que sur Apple Silicon.
Cato note que les opérateurs développent encore le chargeur. Les échantillons plus anciens utilisaient du base64 avec compression ; les plus récents utilisent des conteneurs gzip chiffrés en AES dont la clé est réassemblée à partir de variables dispersées dans le script.
Pour la charge finale, Cato relie le cadre de livraison à Atomic macOS
Stealer : la structure de l'URL du chargeur, la forme de la requête de
télémétrie, le chemin de préparation /tmp/helper, la suppression de xattr,
les URL de charge sur le thème de la mise à jour. Ils qualifient le
recoupement de fort et cohérent et s'arrêtent avant de nommer le binaire, ce
qui est le bon choix et mérite d'être conservé quand on le répète.
L'étape en amont des scanners
Alignez les contrôles que l'industrie a passé deux ans à construire pour les agents de codage. L'analyse de réputation des registres. Les fichiers de verrouillage et les empreintes d'intégrité. La provenance de build et l'attestation. Les SBOM. Les délais minimaux sur les nouvelles versions de paquets. L'analyse statique du code généré. Tous fonctionnent, et tous partent de la même hypothèse : le développeur a déjà une chaîne d'outils qui marche, et le risque est en aval, dans ce qu'il en fait.
Cette campagne se situe en amont de tout cela. La contrefaçon ici, c'est l'agent lui-même, et il arrive avant tout registre, avant tout fichier de verrouillage, dans une commande que le développeur tape de ses propres mains dans son propre terminal. Un scanner n'a aucun artefact à noter, parce que l'artefact est une phrase sur une page web.
Le ciblage est l'autre moitié de l'économie. Quelqu'un qui enchérit sur codex macos download achète la machine d'une personne qui est, à cet instant précis,
en train de mettre en place un agent de codage : une machine qui, dans l'heure,
contiendra un jeton d'API, une clé SSH, un fichier ~/.aws/credentials et un
PAT GitHub, autant de choses qu'un voleur d'informations sait trouver. Le moment
de l'installation est le moment le moins cher pour être là.
Nous avons déjà couvert l'inverse : avec FakeGit et AgentBaiting, c'est l'agent qui cherche et qui tend à l'humain les étapes d'installation. Ici, c'est l'humain qui cherche. Les deux marchent parce que découvrir-puis-coller est la façon dont les logiciels s'installent, et qu'aucun scanner ne se tient à l'une ou l'autre extrémité de cette boucle.
D'où vient la commande d'installation
Bromure Agentic Coding n'a pas de telle boucle, et la raison tient à l'origine de l'agent.
Vous n'allez pas chercher un agent de codage. Codex est un interrupteur dans le panneau Agents d'un profil, à côté de Claude Code et de Grok Build. Activez-le, choisissez son mode d'authentification, et l'agent est là à la session suivante, tournant dans un onglet kitty à l'intérieur de la VM du profil.
Derrière cet interrupteur, il y a une chaîne figée. Bromure provisionne son image de base depuis son propre catalogue, et l'entrée pour Codex tient en une ligne :
npx --yes @socketsecurity/cli npm install -g --silent @openai/codex
Claude Code est @anthropic-ai/claude-code sur le même modèle, Kimi Code est
@moonshot-ai/kimi-code. Les noms de paquets sont compilés dans l'application,
pas découverts. Le registre est registry.npmjs.org, pas l'hôte qu'une iframe
désigne. L'installation passe par le CLI socket.dev, et la requête sort par le
proxy MITM de l'hôte, où s'appliquent les politiques Supply Chain du profil
: le délai de deux jours actif par défaut, plus les recherches OSV, le filtrage
socket.dev ou Delpi, et le retrait des scripts d'installation que vous pouvez
activer.
Ce chemin n'a ni résultat de recherche, ni page à usurper. Le canal que l'attaquant a payé pour empoisonner est absent du flux de travail, et absent n'est pas un contrôle qu'il faut penser à opérer.
Maintenant, collez-la quand même
L'architecture doit survivre au jour où quelqu'un l'ignore. Prenez la campagne, donnez-lui la victoire, et faites-la traverser un profil : quelqu'un trouve le faux portail, copie la commande, et la colle dans le terminal où il fait son travail d'agent, qui dans Bromure Agentic Coding est un onglet kitty à l'intérieur de la VM.
Le binaire ne s'exécute pas. Un Mach-O universel est un exécutable macOS.
L'invité est Ubuntu. xattr n'est pas une commande Linux, et /tmp/helper est
un chemin sur un disque système qui existe pour être jeté. Ressources →
Stockage vous donne Effacer le dossier personnel… pour /home/ubuntu et
Réinitialiser à la base… pour recloner le disque système de l'espace de
travail depuis l'image de base partagée, en lecture seule.
Les trois requêtes ne sortent pas. Chaque étape de cette chaîne a besoin du
réseau : l'URL décodée en base64 qui tire l'étape une, la balise event=pasted,
et le téléchargement de la charge. Garde-fous → Connexions sortantes est une
table de règles à la pf : action, protocole (tcp, udp, web, any), hôte
ou CIDR, ports, et pour web une liste de méthodes HTTP, évaluées de haut en
bas, première correspondance gagnante, avec Trafic non apparié réglé sur
Autoriser ou Refuser. Réglez-le sur Refuser et listez les hôtes dont votre
travail a besoin. bright-links.com n'en fait pas partie. Bromure applique la
table côté hôte, dans le commutateur virtuel et le proxy, si bien que rien de ce
que l'invité fait à son propre environnement ne change la réponse.
L'étape deux est celle sur laquelle il vaut la peine de s'arrêter.
event=pasted est la métrique de conversion de l'opérateur, le ping qui lui dit
qu'une page d'atterrissage fonctionne, et à quel point. Quand cette requête
meurt à l'hôte, il ne reçoit pas un rapport d'infection échouée. Il reçoit du
silence, ce qui se lit comme une impression publicitaire qui n'a jamais
converti.
Le vol rapporte des espaces réservés. Un voleur de la classe d'Atomic vise
les données de navigateur, les portefeuilles et, sur une machine de
développement, les identifiants. Dans un profil Bromure, les vraies valeurs
n'entrent jamais dans la VM. Les clés d'API génériques sont de faux brm_…
exportés en variables d'environnement et échangés sur le fil par le proxy de
l'hôte. Le kubeconfig est synthétique, avec des certificats client jetables. Les
requêtes AWS sont resignées côté hôte, de sorte que tout ce qui contourne le
proxy reçoit InvalidSignatureException. ~/.docker/config.json contient un
faux blob base64. Les clés SSH privées ne sont pas là à lire :
elles n'y ont jamais été. Activez
Exiger une approbation à l'usage par identifiant et chaque échange devient
une boîte de dialogue côté hôte avec une autorisation bornée dans le temps :
cinq minutes, une heure, le reste de la session. Un profil partage au plus huit
dossiers que vous avez choisis, si bien que le reste du Mac n'est pas à un
parcours de répertoire de distance.
La corrélation est déjà sur votre écran. La conclusion de Cato elle-même est qu'aucune étape prise isolément n'expose cette campagne ; la détection a demandé de corréler ensemble la livraison par recherche sponsorisée, le contenu web embarqué, l'exécution dans le Terminal et l'activité sortante. C'est un problème difficile quand vos preuves sont réparties entre un navigateur, un shell et une sonde réseau. Dans un profil, c'est une seule fenêtre : le Journal de sécurité (Fenêtre → Journal de sécurité…) est une table chronologique unique, côté hôte, des verdicts de paquets, des décisions du pare-feu, des échanges d'identifiants et des détections d'injection de prompt. Le code invité ne peut pas la modifier, parce que le code invité ne peut pas l'atteindre.
Activez-le
Le délai est actif par défaut à deux jours. Les autres couches sont des réglages, et elles valent deux minutes : Garde-fous → Connexions sortantes, avec Trafic non apparié sur Refuser et une liste d'autorisation pour les hôtes dont votre travail a besoin. Supply Chain → Vérification de vulnérabilités OSV, plus le filtrage socket.dev ou Delpi si vous avez une clé, et le retrait des scripts d'installation. Identifiants → Exiger une approbation à l'usage sur tout ce qui peut dépenser de l'argent ou détruire des données. Puis laissez la fenêtre du Journal de sécurité ouverte sur un second écran pendant une semaine et voyez à qui parlent vos builds.
Les résultats de recherche sponsorisés vont continuer d'être la porte d'entrée, et les constructeurs de sites sur des domaines de confiance vont continuer d'héberger le perron. Google fera tomber ces pages et trois autres monteront, parce que l'économie, c'est quelques dollars par clic contre un poste de développement avec des identifiants cloud dessus. Installez Bromure Agentic Coding, activez vos agents depuis l'éditeur de profil plutôt que depuis une page de téléchargement, et laissez la prochaine commande collée atterrir dans une machine construite pour être jetée.