← Retour à tous les articles
Publié le · par Renaud Deraison

La mise à jour a ajouté une clé

Pendant onze heures le 29 octobre, la marketplace d'extensions de Cursor a servi une extension Claude Code piégée, sous le nom d'éditeur d'Anthropic. Au chargement, elle ajoutait la clé SSH d'un attaquant, installait un LaunchAgent et tentait d'ouvrir un tunnel inverse, sur les machines de jusqu'à 5 000 développeurs. Dans Bromure Agentic Coding, l'agent ne vient pas d'une marketplace d'éditeur, et une charge comme celle-ci tourne dans une VM que personne ne peut joindre : son tunnel est refusé par le pare-feu sortant et sa persistance disparaît quand on rembobine le home.

Personne n'a eu à ouvrir une conversation ni à approuver un appel d'outil. L'éditeur a chargé l'extension, et 66 lignes de JavaScript ont tourné sous le compte du développeur avant le code de Claude Code lui-même.

Le 29 octobre, entre environ 2 h 27 et 13 h 35, heure du Pacifique, la marketplace d'extensions de Cursor a servi une version piégée de l'extension Claude Code d'Anthropic. L'avis de sécurité de Cursor cite les versions 2.1.312 et 2.1.313 de anthropic.claude-code, publiées sous l'identité d'éditeur d'Anthropic, et précise qu'Anthropic ne les a pas construites. BleepingComputer rapporte que jusqu'à 5 000 développeurs ont été exposés, et The Hacker News note que quiconque avait activé la mise à jour automatique a pu la recevoir sans rien faire.

Les chercheurs de Phorion et d'OpenSourceMalware ont publié leurs analyses le 30 octobre. Cursor a retiré l'extension, fermé sa marketplace le temps de l'auditer et de faire tourner ses clés, et fait mettre hors ligne le serveur de l'attaquant. Personne n'a encore dit comment cette version a pu être publiée sous le nom d'Anthropic.

Ce que faisaient les 66 lignes

L'attaquant n'a pas touché au code de Claude Code : il a placé un chargeur de 66 lignes devant, en tête de extension.js. OpenSourceMalware décrit le schéma : « place a compact backdoor before a large legitimate bundle, suppress errors, and let the expected application continue ». Le chargeur s'exécutait quand l'éditeur chargeait l'extension et ouvrait sa webview. Le développeur n'avait pas à lancer de conversation. Ensuite, la vraie extension se chargeait et fonctionnait normalement.

Entre-temps, le chargeur :

  1. Faisait l'inventaire. Nom d'hôte, nom d'utilisateur, OS, répertoires home et de travail, e-mail git global, IP publique, et les noms de jusqu'à 40 variables d'environnement contenant KEY, TOKEN, SECRET, PASS, AWS ou GCP. Il envoyait le tout en JSON, en HTTP non chiffré, à 134.209.82.225:8099/beacon.
  2. Ajoutait une porte. Il ajoutait une clé Ed25519 portant le commentaire svc-telemetry à ~/.ssh/authorized_keys.
  3. Tentait de l'ouvrir. Sur macOS, il lançait sudo -n systemsetup -setremotelogin on ; sur Linux, il essayait de démarrer sshd ; sur Windows, il installait OpenSSH Server.
  4. Appelait la maison. Il écrivait une clé privée dans un fichier temporaire et se connectait à [email protected] avec -N -R '*:0:localhost:22', un tunnel inverse qui renvoie un port du serveur de l'attaquant vers le port SSH du développeur. Il se reconnectait toutes les 60 secondes.
  5. S'installait pour de bon. Un LaunchAgent utilisateur nommé com.apple.sysmond sur macOS, une entrée crontab @reboot sur Linux, et une tâche planifiée appelée SysMon sous Windows.

Selon BleepingComputer, des erreurs de code ont empêché SSH de s'activer chez beaucoup de victimes. La clé, la persistance et la balise sont arrivées sur ces machines quand même. Cursor conseille de chercher la clé svc-telemetry, de supprimer la persistance, d'envisager de reconstruire la machine, car désinstaller l'extension peut ne pas suffire, et de faire tourner tous les identifiants que la machine pouvait atteindre, « using a trusted system ».

D'une mise à jour d'extension à la clé d'un attaquant sur la machineChargée par l'IDE2.1.312 / 2.1.313,nom d'Anthropic,mise à jour auto1 · Inventairehôte, user, mail git,IP publique, nomsde vars KEY/TOKEN2 · Clésvc-telemetry ajoutéeà authorized_keys,SSH activé3 · Persistancecom.apple.sysmond,crontab @reboot,tâche SysMon4 · Rappeltunnel inversesur :22, balisesur :8099La clé d'un attaquant et un accès retour, sur le compte même du développeurà côté de ~/.ssh, ~/.aws, la session gh et tous les dépôts ; Cursor conseille de reconstruire la machine
Ce que faisait l'extension Claude Code piégée au chargement, d'après l'avis de Cursor et l'analyse d'OpenSourceMalware. Un chargeur de 66 lignes placé devant la vraie extension faisait l'inventaire, ajoutait la clé SSH d'un attaquant, installait une persistance, et ouvrait un tunnel inverse et une balise HTTP vers 134.209.82.225.

Le code le plus digne de confiance de la machine

Une extension d'éditeur tourne avec le compte complet du développeur. Elle peut lire chaque fichier du home, lancer des processus et écrire un LaunchAgent qui survit à l'éditeur. Les marketplaces poussent les mises à jour sans demander, et le nom d'éditeur affiché sur celle-ci était celui d'Anthropic. Un développeur prudent qui avait vérifié l'éditeur avant d'installer a reçu la porte dérobée lui aussi : elle est arrivée sous forme de mise à jour d'une extension installée des semaines plus tôt.

Les agents de code font monter les enjeux. L'extension qui héberge l'agent est celle à qui les développeurs accordent le plus : elle lit tout le dépôt, exécute des commandes et vit dans un processus qui détient les clés d'API et les jetons cloud de l'environnement. Ce chargeur a relevé les noms de ces variables. Lire leurs valeurs demande les mêmes quelques lignes.

Le même matin dans Bromure Agentic Coding

Bromure Agentic Coding fait tourner Claude Code, Codex, Grok, Kimi et omp dans des VM Ubuntu sur votre Mac. Chaque machine est une VM à part, et l'agent, ses dépôts, ses installations de paquets et ses commandes vivent tous à l'intérieur. La conversation et les terminaux dans lesquels vous tapez sont dessinés par l'application sur votre Mac. Les vrais identifiants, le proxy par lequel passe le trafic de la VM et le journal de ce qui s'est passé restent aussi sur le Mac.

L'agent ne vient pas d'une marketplace d'éditeur

Il n'y a pas de marketplace d'extensions sur le chemin : Bromure dessine sa propre fenêtre de conversation sur le Mac. Claude Code est installé dans votre copie de l'image de base de Bromure par une étape de configuration inscrite dans un catalogue signé avec la même clé que les mises à jour de l'application Bromure. Cette étape installe @anthropic-ai/claude-code depuis npm, à travers le scanner de chaîne d'approvisionnement de Socket.dev. OpenSourceMalware range le paquet npm parmi les distributions qui n'ont pas été touchées.

Tout ce que l'agent installe ensuite passe par le proxy sur le Mac, qui applique la politique de chaîne d'approvisionnement de la machine. La barrière d'âge est activée d'origine, avec un minimum de deux jours : les versions npm, PyPI, Cargo, RubyGems et Packagist plus jeunes que cela sont retirées de la liste du registre, si bien que latest désigne la version la plus récente publiée depuis au moins deux jours. La version malveillante de Cursor est restée en ligne onze heures. Une version détournée sur npm avec la même durée de vie n'apparaît jamais dans une machine Bromure. Nous avons détaillé ce cas avec la version PyPI empoisonnée de LiteLLM dans La version avait deux heures.

La clé ouvre une porte que personne ne peut atteindre

Supposons qu'une charge comme celle-ci entre quand même dans une machine, par un dépôt que l'agent clone ou un outil qu'il exécute. Elle tourne sous Ubuntu, avec l'utilisateur de la machine. Elle n'obtient ni votre compte macOS, ni votre Trousseau, ni le ~/.ssh de votre Mac.

Sa clé svc-telemetry va dans le propre authorized_keys de la VM. Les machines sont sur un réseau privé interne à l'application : votre Mac peut les joindre, votre réseau local physique non, et rien de l'extérieur ne peut s'y connecter tant que vous ne publiez pas vous-même un service. La seule voie d'entrée était le tunnel inverse.

Le tunnel ne s'ouvre jamais

Le tunnel exige une connexion SSH sortante vers 134.209.82.225, et la balise du HTTP en clair vers le port 8099 de la même adresse. Chaque connexion de la VM passe par le Mac, où s'applique le pare-feu Outbound connections de la machine. Ses règles portent sur l'hôte, la plage d'IP, le protocole et le port, et avec Unmatched traffic réglé sur Deny, seuls les hôtes que vous avez listés passent. Une IP DigitalOcean sur le port 22 ne figure sur la liste de personne. Le pare-feu refuse le tunnel, chaque nouvelle tentative toutes les 60 secondes, et la balise.

Chaque refus apparaît dans la Security Timeline sur votre Mac, avec l'hôte, le port, le protocole et le verdict. Un refus vers la même IP chaque minute se remarque, et vous le voyez pendant que l'attaquant attend encore sa connexion.

L'inventaire ne vaut rien

La liste de noms de variables de la balise aurait trouvé de quoi faire dans une machine Bromure : ANTHROPIC_API_KEY, un jeton GitHub, des réglages AWS. Chaque valeur est un substitut. Les vrais identifiants sont chiffrés sur le Mac, et le proxy ne remplace un substitut par sa vraie valeur que dans les requêtes vers l'hôte auquel il appartient. Les clés privées SSH ne sont pas du tout dans la VM. SSH_AUTH_SOCK est un pont vers le Mac qui renvoie des signatures, et le ssh-agent de votre Mac n'est jamais exposé. Un chargeur qui serait allé jusqu'à lire les valeurs aurait obtenu des chaînes qu'aucun serveur n'accepte. S'il en avait envoyé une à son propre serveur, le proxy aurait bloqué la requête, mis la VM en pause et affiché This environment may have been compromised, en nommant l'identifiant et la destination.

Le nettoyage prend une minute

Cursor dit aux développeurs touchés de supprimer la clé et la persistance, d'envisager de reconstruire la machine et de faire tourner leurs identifiants depuis un système de confiance. Dans Bromure, la reconstruction tient en deux éléments de menu. Bromure garde un point de contrôle copy-on-write du home de chaque machine à chaque démarrage. Rewind home… ramène /home/ubuntu à un démarrage antérieur à l'exécution de la charge, et emporte avec lui la clé en trop et le lanceur ~/.config/.smt. Reset disk reclone le disque système depuis l'image de base et emporte la crontab. Les réglages, identifiants et clés SSH de la machine survivent aux deux.

Le système de confiance que demande Cursor, c'est le Mac, qui n'a jamais exécuté la charge. Il n'y a rien à faire tourner, puisque la VM n'a jamais détenu un seul vrai identifiant.

Éditeur sur un portable : le chargeur tourne en votre nomL'extension se met à jour et se chargedans votre compte macOS, à côté de vos vraies clésClé et persistance sur le Macsvc-telemetry dans ~/.ssh/authorized_keys,LaunchAgent com.apple.sysmondDirectement vers 134.209.82.225tunnel inverse sur :22 toutes les 60 s, balise sur :8099 ;remède : reconstruire, tout faire tournerBromure : la charge tourne dans une VMVM de la machine (Ubuntu)clé dans l'authorized_keys de la VM ; substituts seulschaque connexion via le MacPare-feu sortant sur votre Mac134.209.82.225:22 tunnel : refusé134.209.82.225:8099 balise : refuséechaque tentative dans la Security Timelinepuis, machine arrêtéeRewind home… et Reset diskclé, lanceur, crontab partis ; réglages et clés gardés
La même charge dans une machine Bromure. Elle tourne dans la VM Ubuntu de la machine, ajoute sa clé au propre authorized_keys de la VM sur un réseau que personne ne peut joindre de l'extérieur, et ne trouve que des identifiants de substitution. Son tunnel et sa balise passent par le Mac, où le pare-feu sortant les refuse et où la Security Timeline enregistre chaque tentative. Rewind home et Reset disk suppriment la persistance ; le Mac et ses vrais identifiants restent intacts.

Donnez au travail risqué sa propre machine

Les identifiants et les règles de pare-feu se règlent machine par machine, et les machines ne coûtent rien à créer. Une machine qui essaie de nouveaux outils, plugins et kits de démarrage peut n'avoir aucun identifiant de production et un pare-feu qui refuse tout sauf ses registres de paquets. La machine qui déploie garde ses identifiants, avec une approbation exigée avant chaque utilisation. Pour une expérience ponctuelle, bromure-cli vm run --rm crée une machine supprimée dès qu'elle s'arrête.

Pas de marketplace sur le chemin

La conversation fait partie de l'application. Claude Code vient du paquet npm d'Anthropic, par une étape de configuration signée, scannée par Socket.dev.

Deux jours avant toute nouveauté

La barrière d'âge masque les versions de paquets de moins de deux jours. Une version détournée qui vit onze heures n'est jamais résolue.

Une porte que personne ne peut atteindre

Une clé plantée atterrit dans le propre authorized_keys de la VM, sur un réseau privé auquel ni votre réseau local ni Internet ne peuvent se connecter.

Refuser l'hôte inconnu

Avec Unmatched traffic réglé sur Deny, le tunnel inverse et la balise sont refusés, et chaque tentative est enregistrée sur le Mac.

Des substituts dans la VM

Chaque clé d'API et chaque jeton de la VM est un substitut, et les clés privées SSH n'y entrent jamais. L'inventaire ne vaut rien.

Rembobiner plutôt que reconstruire

Rewind home et Reset disk suppriment les fichiers et la persistance de la charge. Réglages, identifiants et clés restent.

L'outil qui fait tourner l'agent fait partie de la surface d'attaque

Ni Cursor ni Anthropic n'ont dit comment cette version est sortie sous le nom d'Anthropic. Pour votre propre machine, l'incident tranche un point. Le logiciel qui héberge votre agent de code tourne avec votre compte et se met à jour tout seul, et un nom d'éditeur de confiance sur la mise à jour ne prouve rien sur son contenu.

Dans Bromure Agentic Coding, votre agent et tout ce qu'il touche tournent dans une VM sur votre Mac. Cette VM ne détient que des substituts, ne joint que les hôtes que vous autorisez, et peut être ramenée à un démarrage antérieur au moment où quelque chose a mal tourné. Les vraies clés ne quittent jamais le Mac.

Sur les voleurs d'identifiants qui collectent désormais les jetons et historiques des agents de code, lisez Ils ont ajouté votre agent à la liste. Sur une compromission partie du portable d'un développeur et arrivée à 6,3 milliards de dollars, lisez Le portable était la porte d'entrée.