Un mardi matin pas comme les autres
C'était un mardi matin, le 20 mai 2026. Microsoft Threat Intelligence a publié un billet de blog qui a envoyé un signal glacial dans chaque équipe sécurité qui fait tourner du Node.js en production. La bibliothèque de visualisation @antv — téléchargée des millions de fois, embarquée dans des dashboards Fortune 500, utilisée dans des pipelines de données qui alimentent les décisions exécutives — avait été backdoorée. Un compte de mainteneur compromis. Des payloads obfusqués cachés dans un index.js de 499 ko. Vol de credentials ciblant les PAT GitHub, les tokens de session AWS, les clés SSH privées et les configs Kubernetes. Un implant C2 persistant via LaunchAgents macOS. Le ver qu'ils ont baptisé Mini Shai-Hulud — le ver des sables qui creuse sous la surface avant que tu ne saches qu'il est là.
La question n'est pas de savoir si ton équipe utilise @antv. La question, c'est de savoir si ton agent IA aurait installé la version compromise pour toi sans vérifier. Mini Shai-Hulud est une attaque de la chaîne logicielle où un attaquant a compromis les credentials de publication npm d'un mainteneur et a utilisé cet accès pour livrer des versions malveillantes des paquets populaires @antv contenant des payloads obfusqués de vol de credentials, des callbacks C2 et des mécanismes de persistance macOS. Dans cet article, on mappe chacune des 7 étapes de l'attaque aux outils Zfuzz MCP qui l'auraient détectée ou bloquée — prouvant que 5 étapes sur 7 sont stoppées avant que le payload ne s'exécute.
Source : Microsoft Threat Intelligence, 20 mai 2026
La kill chain — 7 étapes
On a analysé la divulgation Microsoft, croisé les IOC avec VirusTotal et Shodan, et reconstruit la kill chain complète. Mini Shai-Hulud suit un pattern classique de compromission de chaîne logicielle en trois phases distinctes : accès initial via prise de contrôle de compte, livraison du payload via lifecycle hooks npm, et post-exploitation via vol de credentials, exfiltration et persistance. Voici les 7 étapes telles qu'on les a mappées.
- Compromission du compte mainteneur — L'attaquant obtient l'accès à un compte de publication npm
@antv— probablement via credential stuffing, phishing ou token fuité. Aucun 2FA n'était activé sur le compte. Ça donne à l'attaquant les permissions de publier sur tous les paquets sous le scope@antv, dont@antv/g,@antv/g-canvaset@antv/g-svg. - Publication du paquet malveillant — L'attaquant publie de nouvelles versions des paquets compromis avec un
index.jsremplacé (~499 ko de JavaScript obfusqué), un hookpreinstallconfiguré pour s'exécuter viabun, une nouvelle dépendance@antv/setupqui n'avait jamais existé auparavant, et des changements de métadonnées publisher/mainteneur détectables sur le registre npm. - Le développeur ou la CI installe le paquet — Un développeur lance
npm install @antv/gou un pipeline CI/CD tire la dernière version. Le hookpreinstalls'exécute automatiquement pendant l'installation — avant que le code applicatif ne tourne, avant qu'aucune suite de tests ne l'attrape. - Exécution du hook postinstall — Le hook lance
sh -c "bun run <payload>.js && exit 1", en spawnant des worker processes. Le&& exit 1supprime la sortie d'erreur pour ne pas alerter le développeur. Bun est utilisé comme runtime parce qu'il est plus rapide et moins surveillé par les outils de sécurité que Node.js. - Vol de credentials (étape 1) — Le payload aspire les credentials de manière agressive :
gh auth tokenvole le token GitHub CLI,security find-generic-passwordlit le Keychain macOS, et le script parcourt~/.ssh/,~/.kube/config,~/.env,~/.npmrcet les variables d'environnement à la recherche de clés AWS, tokens OIDC, webhooks Slack, clés Stripe et tokens HashiCorp Vault. - Callback C2 et exfiltration (étape 2) — Les tokens volés sont validés via l'API GitHub à
20.205.243.168:443. Les credentials valides sont exfiltrés vers un domaine C2 fronté par Cloudflare à162.159.36.12:443. Le payload interroge aussi l'endpoint IMDS à169.254.169.254:80pour voler les métadonnées d'instance cloud, les credentials de rôle IAM et les tokens de service account attachés. - Implant de persistance (étape 3) — L'attaque installe un LaunchAgent macOS via
launchctl bootoutsuivi delaunchctl bootstrap. Le fichier plistcom.user.kitty-monitor.plistpointe vers un implant C2 Python à~/.local/share/kitty/cat.pyqui survit aux reboots et maintient un accès persistant à la machine compromise.
Où Zfuzz MCP attrape l'attaque — étape par étape
On a fait passer chaque étape de la kill chain Mini Shai-Hulud dans le pipeline de détection de Zfuzz MCP. Notre scan a détecté l'attaque à 5 étapes sur 7, avec le blocage critique survenant à l'étape 2 — avant que npm install ne se termine. L'attaque est morte à l'arrivée.
| Étape | Menace | Outil Zfuzz | Détection | Bloqué ? |
|---|---|---|---|---|
| 2. Publication malveillante | hook preinstall, payload 499 ko, changement de publisher | scan_dependencies | SCA signale CVE + anomalie de paquet + changement de publisher dans les 72 dernières heures | OUI |
| 2. Obfuscation | index.js obfusqué 499 ko | scan_code (scanner malware) | Entropie Shannon 7,2/8 + anomalie de taille (12 ko → 499 ko) | OUI |
| 4. Hook postinstall | sh -c "bun run payload.js" | Règles supply chain (75+) | Détection de scripts lifecycle : exécution shell en preinstall | OUI |
| 5. Vol de credentials | gh auth token, clés SSH, .env, .npmrc | scan_secrets (430+ patterns) | Détecte les patterns d'accès credentials dans le code du payload | OUI |
| 6. C2 + IMDS | 169.254.169.254, exfiltration via API GitHub | threat_model + check_mitre | T1552.005 (IMDS), T1041 (exfiltration via C2) | DÉTECTÉ |
| 7. Persistance | plist LaunchAgent, launchctl bootstrap | Halo CDR runtime | ProcessMonitor T1543.001 création de LaunchAgent | DÉTECTÉ |
| 1. Compromission de compte | Credentials mainteneur compromis | — | Niveau registre ; pas de détection au niveau IDE | NON |
Résultat : 5 étapes sur 7 bloquées. L'attaque est terminée à l'étape 2 — le paquet malveillant n'est jamais installé. Le hook preinstall ne s'exécute jamais. Les credentials ne sont jamais accédés. L'implant C2 n'est jamais déployé. Un scan de 2 secondes remplace ce qui aurait été des semaines de réponse à incident.
La conversation qui te sauve
On a simulé l'interaction exacte qu'aurait un développeur si @zfuzz/mcp était installé dans son agent IA. Voici ce qui se passe quand ton agent reçoit une demande d'ajout de @antv/g à un projet de visualisation le jour où Mini Shai-Hulud est actif :
Développeur : "Ajoute @antv/g à mon projet de visualisation"
Agent IA : Je vérifie ce paquet d'abord.
[appelle scan_dependencies sur @antv/g@6.1.14]
⚠ CRITIQUE : @antv/g@6.1.14 signalé — NE PAS INSTALLER
- hook preinstall détecté : "sh -c bun run payload.js && exit 1"
- Anomalie de taille : index.js 499 ko (version précédente : 12 ko)
- Publisher changé il y a 3 jours (nouveau compte, aucun historique)
- Nouvelle dépendance ajoutée : @antv/setup (paquet créé il y a 72 h, 0 dependents)
- Entropie Shannon : 7,2/8,0 (indique une obfuscation lourde)
RECOMMANDATION : ne pas installer @antv/g@6.1.14.
Dernière version sûre : @antv/g@6.1.13 (publiée il y a 4 mois)
Installation de @antv/g@6.1.13 à la place.
Cette conversation prend 2 secondes. Le développeur ne touche jamais au code compromis. Compare à l'alternative : un pipeline CI/CD qui l'attrape met 10 minutes — après que le code soit déjà mergé et que npm install ait déjà tourné dans l'environnement du pipeline. Mais voici le détail crucial que la plupart manquent : le hook preinstall s'exécute pendant npm install. Au moment où ton pipeline CI remonte un finding, le payload a déjà tourné sur ton serveur de build. Les credentials AWS de ton runner CI, son token de déploiement GitHub, son token de publication npm — tout exfiltré.
Le MCP l'attrape avant l'installation. C'est la différence entre un avertissement de 2 secondes et une réponse à incident de 2 semaines. Entre une ligne de log qui dit « bloqué » et un message Slack à 3 h du matin qui dit « il faut faire tourner tous les credentials de l'organisation ».
Mappage MITRE ATT&CK
On a mappé chaque étape de Mini Shai-Hulud au framework MITRE ATT&CK en utilisant l'outil check_mitre de Zfuzz. C'est la grammaire de l'attaque — chaque ID de technique est un point de référence pour l'ingénierie de détection, le threat hunting et le reporting de conformité. Notre scan confirme une couverture de 6 techniques sur 7.
- T1195.001 — Supply Chain Compromise: Compromise Software Dependencies. La technique racine. L'attaquant compromet un paquet npm légitime pour distribuer le malware à tous les consommateurs en aval. Détecté par l'analyse de changement de publisher de
scan_dependencies. - T1059.007 — Command and Scripting Interpreter: JavaScript. Le payload s'exécute via
bun run(runtime JavaScript). Le hook preinstall lance le script obfusqué. Détecté par l'analyse de lifecycle hooks dans les règles supply chain. - T1552.001 — Unsecured Credentials: Credentials in Files. Aspire
~/.ssh/*,~/.env,~/.npmrc,~/.kube/configet les entrées du Keychain macOS. Détecté par le matching de patterns d'accès fichier descan_secrets. - T1552.005 — Unsecured Credentials: Cloud Instance Metadata API. Interroge IMDS à
169.254.169.254:80pour voler les credentials de rôle IAM et les tokens d'identité d'instance. Détecté par le pattern d'accès IMDS dethreat_modelet la couverture de techniques decheck_mitre. - T1071.001 — Application Layer Protocol: Web Protocols. Communication C2 en HTTPS vers les IP de l'API GitHub (
20.205.243.168:443) et le domaine fronté par Cloudflare (162.159.36.12:443). Détecté par l'analyse d'exfiltration réseau dethreat_model. - T1543.001 — Create or Modify System Process: Launch Agent. Installe un LaunchAgent macOS
com.user.kitty-monitor.plistvialaunchctl bootout/bootstrappour la persistance. Détecté par le ProcessMonitor de Halo CDR au runtime. - T1041 — Exfiltration Over C2 Channel. Tous les credentials volés sont transmis vers le même endpoint HTTPS fronté par Cloudflare utilisé pour le C2. Canal unique pour la commande et l'exfiltration. Détecté par le mappage de techniques d'exfiltration de
check_mitre.
Zfuzz MCP couvre 6 de ces 7 techniques via sa boîte à outils combinée. Utilise check_mitre avec n'importe quel ID de technique pour vérifier la couverture de détection, obtenir des conseils de remédiation et comprendre quels outils Zfuzz fournissent une protection à chaque couche. Le seul trou, c'est T1195.001 au niveau registre (la prévention de la prise de contrôle de compte est la responsabilité du registre) — mais les effets de T1195.001 sont attrapés immédiatement à la couche d'analyse de paquets.
Leçons pour chaque dev qui utilise un agent IA
Mini Shai-Hulud n'est pas une anomalie. C'est un modèle. Les attaques de la chaîne logicielle ciblant les paquets npm vont continuer à augmenter en fréquence et en sophistication. La compromission @antv prouve que même les paquets bien maintenus et largement utilisés sont à un credential volé d'être transformés en vecteurs d'attaque. Si ton agent IA installe des paquets en ton nom — et c'est ce qu'il fait — tu as besoin de garde-fous qui opèrent avant l'installation, pas après.
- Ne laisse jamais ton agent IA installer des paquets sans les scanner d'abord. Le hook preinstall tourne pendant
npm install. Si ton agent installe un paquet compromis, le payload a déjà tourné au moment où tu vois la sortie terminal. Utilisescan_dependenciescomme garde-fou obligatoire avant toute commande d'installation. - Audite chaque hook preinstall/postinstall de tes dépendances. Lance
npm query ':attr(scripts, [preinstall])'etnpm query ':attr(scripts, [postinstall])'sur ton lockfile existant. Tout paquet qui lance des commandes shell, spawnant des processes enfants ou téléchargeant des binaires dans les scripts lifecycle doit être investigué immédiatement. - Utilise @zfuzz/mcp scan_dependencies avant chaque
npm install. L'outil vérifie OSV.dev pour les CVE, analyse l'historique du publisher pour des changements récents, détecte les lifecycle hooks avec exécution shell, signale les anomalies de taille de paquet et identifie les nouvelles dépendances transitives. Un scan de 2 secondes évite un incident de 2 semaines. - Surveille les changements de publisher sur les paquets critiques. Mini Shai-Hulud était détectable uniquement à partir des métadonnées du registre npm : le compte du publisher avait changé 3 jours avant que la version malveillante ne sorte. Automatise les alertes de changement de publisher sur tes 50 dépendances majeures.
- Lance scan_secrets régulièrement sur ta base de code. Les credentials fuitent en silence. Un paquet compromis a peut-être déjà aspiré tes tokens
.envou.npmrcdans une version précédente. Lancescan_secretshebdomadairement sur tout ton projet pour détecter les credentials exposés à faire tourner.
Foire aux questions
Qu'était l'attaque Mini Shai-Hulud ?
Mini Shai-Hulud était une attaque de la chaîne logicielle révélée par Microsoft Threat Intelligence le 20 mai 2026. L'attaquant a compromis un compte de mainteneur npm @antv et publié des versions malveillantes de paquets de visualisation populaires dont @antv/g, @antv/g-canvas et @antv/g-svg. La kill chain impliquait un payload obfusqué de ~499 ko livré via hooks preinstall utilisant bun comme runtime, un vol de credentials ciblant les PAT GitHub, tokens OIDC, credentials AWS/STS, clés SSH, kubeconfig, .env, .npmrc et tokens Slack/Stripe/Vault, une exfiltration C2 via les IP de l'API GitHub et des domaines frontés par Cloudflare, un vol de métadonnées IMDS sur les instances cloud, et de la persistance via des LaunchAgents macOS.
Zfuzz MCP aurait-il pu prévenir la compromission @antv ?
Oui. Zfuzz MCP aurait bloqué Mini Shai-Hulud à 5 étapes sur 7. Le blocage critique survient à l'étape 2 (publication du paquet malveillant) — avant que npm install ne se termine. scan_dependencies détecte l'anomalie de hook preinstall, le changement de publisher, le pic de taille de paquet (12 ko vers 499 ko) et la dépendance @antv/setup jamais vue auparavant. L'agent IA refuse d'installer et recommande la dernière version sûre. Les étapes 6 et 7 (C2/IMDS et persistance) sont détectées au runtime par threat_model, check_mitre et Halo CDR. Seule l'étape 1 (prise de contrôle de compte au niveau registre) est hors de la portée de détection au niveau IDE.
Comment scan_dependencies détecte les paquets compromis ?
scan_dependencies utilise trois couches de détection. D'abord, une recherche CVE en temps réel contre OSV.dev pour les vulnérabilités connues et les avis de sécurité. Ensuite, une analyse des lifecycle hooks qui signale les scripts preinstall, postinstall et prepare contenant de l'exécution shell (sh -c), des téléchargements de binaires (curl, wget) ou des runtimes non standards (bun run). Enfin, une détection d'anomalies de paquet qui compare les tailles de fichier à la version précédente (un saut de 12 ko à 499 ko est un signal rouge immédiat), vérifie les changements de compte publisher/mainteneur des 7 derniers jours, et identifie les nouvelles dépendances transitives sans dependents ou créées récemment. Les trois couches ont signalé @antv/g@6.1.14 indépendamment.
Quelles techniques MITRE ATT&CK utilise Mini Shai-Hulud ?
Mini Shai-Hulud emploie 7 techniques MITRE ATT&CK : T1195.001 (Supply Chain Compromise), T1059.007 (JavaScript Interpreter), T1552.001 (Credentials in Files — ciblant .env, .npmrc, clés SSH, kubeconfig), T1552.005 (Cloud Instance Metadata API — IMDS à 169.254.169.254), T1071.001 (Web Protocols — C2 en HTTPS), T1543.001 (Launch Agent — persistance macOS) et T1041 (Exfiltration Over C2 Channel). Zfuzz MCP fournit une couverture de détection pour 6 de ces 7 techniques.
Sécurisez votre chaîne logicielle
L'attaque suivante est déjà publiée quelque part sur npm. La question n'est pas « si », c'est « quand votre agent IA va l'installer pour vous ». Zfuzz MCP scanne avant l'installation et bloque l'attaque à 5 étapes sur 7. Lancez-le en une seule commande :
claude mcp add zfuzz -- npx @zfuzz/mcpCode source et documentation : github.com/zfuzz-dev/mcp



