Aller au contenu
medium

Shai-Hulud revient : un ver npm pille l'écosystème AntV

9 min de lecture

Ce matin, en parcourant ma veille supply chain, un nom est ressorti deux fois, sur deux sources indépendantes : Shai-Hulud. J'ai d'abord cru à un énième paquet npm vérolé, le genre d'incident qu'on voit passer chaque semaine. En lisant les détails, j'ai compris que c'était d'une autre ampleur.

Le 19 mai 2026, une nouvelle vague de ce ver npm a compromis des dizaines de paquets de l'écosystème AntV, la suite de visualisation de données d'Alibaba. Pas un paquet obscur : des bibliothèques téléchargées des millions de fois par semaine. Et le ver ne se contente pas de voler — il se propage, en réutilisant les jetons qu'il dérobe.

Dans ce billet, je raconte ce que j'ai compris du mode opératoire, le détail qui m'a fait tiquer en tant qu'utilisateur quotidien de Claude Code, et la première chose que j'ai faite : vérifier mon propre package-lock.json.

Ce qui a remonté dans ma veille

Deux articles, publiés le même jour, décrivaient le même incident sous deux angles. StepSecurity a publié une analyse technique détaillée du payload et de son comportement runtime. Sonatype a pris du recul avec un titre qui résume tout : « les comptes de mainteneurs restent la cible facile ».

Quand deux sources sérieuses convergent en quelques heures sur un sujet, ce n'est plus du bruit de fond. C'est un incident actif qui mérite qu'on s'arrête.

Le compte à l'origine de la fuite n'a rien d'anonyme. Le compte npm atool publie timeago.js — 1,5 million de téléchargements hebdomadaires — et fait partie de l'équipe de maintenance d'AntV. Le namespace @antv regroupe plus de 100 paquets de graphiques, cartographie et rendu. Un seul compte compromis, et c'est tout un pan de l'écosystème JavaScript qui devient un vecteur.

Le mode opératoire

Ce qui m'a frappé, c'est la discipline de l'attaque. Elle ne ressemble pas à un script bricolé.

Les paquets malveillants ont été publiés en deux vagues coordonnées, à 01:56 puis 02:06 UTC. Dix minutes d'écart, un incrément mineur de version à chaque fois. Le but est limpide : faire passer les publications pour des mises à jour de routine et garantir qu'au moins un canal de livraison fonctionne, quel que soit l'environnement de la victime.

Pour s'exécuter, le ver utilise deux mécanismes déclenchés par un simple npm install. Le premier est classique : un script preinstall ou postinstall dans le package.json. Le second est plus retors : une optionalDependencies qui pointe vers un commit empoisonné dans le dépôt GitHub légitime antvis/G2. Le hook prepare de ce commit déclenche le payload. Comme aucune entrée scripts n'apparaît dans l'archive npm elle-même, ce mécanisme passe sous le radar des outils d'analyse statique qui inspectent les paquets publiés.

Le payload est un fichier JavaScript obfusqué de près de 500 Ko, exécuté par le runtime Bun — installé silencieusement à la volée s'il est absent. J'ai déjà décrit ce type de technique, hooks d'installation et fichiers de configuration exécutables, dans le guide Attaques via les gestionnaires de paquets en CI/CD. Shai-Hulud en est l'illustration grandeur nature.

Ce que le payload emporte

C'est ici que l'incident change de catégorie. Le payload n'est pas un simple voleur de jeton npm. Il vise tout ce qui ressemble à un secret.

Sa capacité la plus inquiétante cible les runners GitHub Actions. Le code lit directement la mémoire du processus Runner.Worker, via /proc/[pid]/mem, pour en extraire les secrets CI/CD en clair. Le masquage des logs, sur lequel beaucoup d'équipes se reposent, ne sert strictement à rien face à ça : le secret est lu avant d'être masqué.

Il ne s'arrête pas aux pipelines. Le payload balaie plus de 130 chemins de fichiers sur la machine : identifiants AWS, GCP, Azure, fichiers ~/.kube/config, jetons HashiCorp Vault, ~/.npmrc, ~/.docker/config.json, clés SSH privées, portefeuilles de cryptomonnaies, cookies de messagerie.

Les données volées repartent par deux canaux. Le principal est un dépôt-relais via l'API GitHub, dans le dépôt antvis/G2 lui-même. Le secours est un serveur de commande, t.m-kosche.com, déguisé en collecteur OpenTelemetry — un choix malin, car beaucoup d'organisations laissent passer le trafic d'observabilité sans le filtrer.

Le ver se sert de ce qu'il vole

La plupart des attaques supply chain s'arrêtent à l'exfiltration. Shai-Hulud, non. Il utilise les jetons volés.

Au moment où les chercheurs écrivaient leur analyse, plus de 2 500 dépôts GitHub publics avaient déjà été créés avec des jetons dérobés, chacun nommé avec des termes de l'univers de Dune. Ce chiffre n'est pas anecdotique : il donne une borne basse du nombre d'environnements réellement compromis. Chaque dépôt créé, c'est au moins un jeton qui fonctionnait.

C'est cette boucle — voler des jetons, s'en servir pour publier et créer de l'infrastructure, recommencer — qui justifie le mot ver. L'attaque n'a pas un début et une fin nets ; elle s'auto-alimente. C'est ce qui en fait l'une des plus grandes campagnes supply chain npm documentées à ce jour.

La première chose que j'ai faite

Avant d'écrire quoi que ce soit, j'ai vérifié mon propre terrain. Ce blog tourne sur Astro, donc sur npm, avec quelques centaines de dépendances. Une seule commande suffit à lever le doute :

Fenêtre de terminal
grep -E '"@antv|echarts-for-react|jest-canvas-mock|jest-date-mock|timeago' package-lock.json

Aucun résultat. Sur les 905 dépendances de mon package-lock.json, aucun paquet compromis — un site Astro Starlight n'a pas besoin de bibliothèques de visualisation AntV. Soulagement, mais réflexe à garder : ce contrôle prend dix secondes et doit devenir un automatisme à chaque alerte de ce type.

Si la commande renvoie quelque chose, le raisonnement change du tout au tout. Il faut alors considérer que tous les secrets accessibles dans cet environnement sont compromis, et les renouveler immédiatement : GITHUB_TOKEN, NPM_TOKEN, clés cloud, jetons Vault, clés SSH. Tant qu'un jeton n'est pas révoqué, traitez-le comme une porte ouverte.

Comment se protéger

Au-delà du contrôle ponctuel, cet incident est un bon prétexte pour durcir durablement ses installations npm. Quatre mesures changent vraiment la donne.

Épingler les versions. Installer avec npm ci à partir d'un lockfile, sans plages de versions flottantes. Une version flottante, c'est accepter d'avance le prochain paquet malveillant.

Désactiver les scripts d'installation. npm install --ignore-scripts, ou ignore-scripts=true dans .npmrc, neutralise les hooks preinstall et postinstall — exactement le premier mécanisme de Shai-Hulud.

Imposer un délai de quarantaine. Refuser les versions publiées depuis moins de quelques jours. Une version malveillante est généralement détectée et retirée vite ; attendre, c'est laisser la communauté essuyer les plâtres à votre place.

Durcir les runners CI. Un contrôle du trafic réseau sortant et la détection des lectures mémoire du runner bloquent l'exfiltration. Dans les tests de StepSecurity, ce sont précisément ces deux protections qui ont stoppé l'attaque. J'ai détaillé la mécanique des secrets qui fuient dans un pipeline dans Empoisonnement des variables d'environnement, et les bonnes pratiques d'épinglage dans Sécuriser ses dépendances.

Ce que je retiens

  • Shai-Hulud est un ver npm auto-répliquant ; la vague du 19 mai 2026 a visé l'écosystème AntV, mais le schéma se répétera.
  • Le compromis se déclenche au simple npm install, par un hook preinstall ou une optionalDependencies piégée qui échappe à l'analyse statique.
  • Le payload vole les secrets CI/CD en clair, plus de 130 fichiers d'identifiants, et plante des backdoors dans Claude Code et VS Code.
  • Vérifier son package-lock.json prend dix secondes : ça doit devenir un réflexe à chaque alerte.
  • Les mesures durables sont connues : épingler, --ignore-scripts, quarantaine, durcissement des runners. Cet incident rappelle juste qu'elles ne sont plus optionnelles.

Pour aller plus loin

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn