- Le package npm malveillant Shai-Hulud 2.0 a compromis la machine d’un développeur et permis de s’emparer de l’accès à l’organisation GitHub de Trigger.dev
- L’infection a commencé lorsque le développeur a exécuté
pnpm install, ce qui a déclenché le script preinstall du package malveillant ; l’outil TruffleHog a ensuite été utilisé pour voler des identifiants
- Pendant 17 heures, l’attaquant a cloné 669 dépôts, puis a tenté en 10 minutes de forcer des pushs sur 199 branches et de fermer 42 PR
- Les packages et les systèmes de production n’ont pas été compromis ; l’attaque a été détectée en 4 minutes et l’accès au compte a été bloqué
- Après l’incident, l’équipe a renforcé sa sécurité avec la désactivation des scripts npm, la mise à niveau vers pnpm 10, le déploiement npm via OIDC et la protection systématique des branches
Vue d’ensemble de l’attaque
- Le 25 novembre 2025, pendant un débogage interne sur Slack, une anomalie a été repérée : plusieurs dépôts recevaient un commit « init » au nom de Linus Torvalds
- L’enquête a montré que le ver de supply chain Shai-Hulud 2.0 avait compromis la machine d’un développeur et volé des identifiants GitHub
- Ce ver aurait infecté plus de 500 packages npm et affecté plus de 25 000 dépôts
- Les packages npm officiels de Trigger.dev (
@trigger.dev/*, CLI) n’ont pas été infectés
Chronologie de l’attaque
- 24 novembre, 04:11 UTC : début de la diffusion du package malveillant
- 20:27 UTC : infection de la machine d’un développeur en Allemagne
- 22:36 UTC : premier accès de l’attaquant et début du clonage massif de dépôts
- 15:27~15:37 UTC (25 novembre) : phase d’attaque destructrice pendant 10 minutes
- 15:32 UTC : détection de l’anomalie et blocage de l’accès en 4 minutes
- 22:35 UTC : restauration complète de toutes les branches
Processus d’infection
- Quand le développeur a exécuté
pnpm install, le script preinstall du package malveillant s’est lancé, a téléchargé puis exécuté TruffleHog
- TruffleHog a analysé et exfiltré les tokens GitHub, identifiants AWS, tokens npm, variables d’environnement, etc.
- Le répertoire
.trufflehog-cache et des fichiers associés ont été retrouvés sur la machine infectée
- Le package à l’origine de l’infection ayant été supprimé, il n’a pas pu être retracé
Activité de l’attaquant
- Après l’infection, une phase de reconnaissance a duré 17 heures
- 669 dépôts ont été clonés via une infrastructure située aux États-Unis et en Inde
- Les activités du développeur ont été surveillées afin de conserver l’accès via le token GitHub
- Un dépôt nommé « Sha1-Hulud: The Second Coming » a été créé, probablement pour stocker des identifiants
- Puis, une phase de destruction de 10 minutes a suivi
- Tentatives de push forcé sur 199 branches dans 16 dépôts
- Fermeture de 42 PR, certaines ayant été bloquées par la protection de branche
- Tous les commits apparaissaient sous la forme « Linus Torvalds <email> / init »
Détection et réponse
- L’anomalie a été détectée en temps réel via des alertes Slack
- En 4 minutes, l’accès GitHub du compte compromis a été bloqué, puis tous les accès aux services AWS, Vercel, Cloudflare, etc. ont été révoqués
- L’analyse des logs AWS CloudTrail a montré uniquement des appels API en lecture seule, sans accès aux données de production
- AWS a aussi détecté séparément une activité suspecte liée à Shai-Hulud et envoyé une alerte
Impact et restauration
- 669 dépôts clonés, 199 branches visées par des pushs forcés, 42 PR fermées
- L’absence de reflog côté serveur sur GitHub a compliqué la restauration, mais l’équipe a pu tout rétablir en 7 heures grâce à l’Event API et aux reflogs locaux
- Les packages npm et l’infrastructure de production n’ont pas été compromis
Exposition d’une clé GitHub App
- Pendant l’enquête, une clé privée GitHub App a été retrouvée dans la corbeille du laptop du développeur
- Cette clé disposait de droits read/write sur les dépôts clients et a été immédiatement renouvelée
- La base de données (où sont stockés les ID d’installation) n’ayant pas été compromise, aucune preuve d’accès aux dépôts clients n’a été trouvée, sans qu’un risque puisse être totalement exclu
- Des logs supplémentaires ont été demandés au support GitHub et un e-mail d’information a été envoyé aux clients
Analyse technique de Shai-Hulud
- Lors de l’exécution de
setup_bun.js, le runtime Bun est installé et bun_environment.js est lancé en arrière-plan
- TruffleHog est utilisé pour collecter les identifiants présents dans le répertoire
$HOME
- Les données collectées (
contents.json, cloud.json, truffleSecrets.json, etc.) sont téléversées vers des dépôts GitHub aléatoires avec un encodage base64 triple
- Si un token npm est présent, le ver modifie et republie les packages du compte infecté afin de se propager
- En l’absence d’identifiants, il tente de supprimer le répertoire personnel
- Fichiers indicateurs de compromission :
setup_bun.js, bun_environment.js, .trufflehog-cache/, etc.
Mesures de renforcement de la sécurité
- Désactivation complète des scripts npm (
ignore-scripts=true)
- Mise à niveau vers pnpm 10 : scripts désactivés par défaut, configuration de
minimumReleaseAge (3 jours) pour retarder l’installation de nouveaux packages
- Adoption de npm Trusted Publishers basé sur OIDC pour éliminer les tokens de longue durée
- Protection de branche activée sur tous les dépôts
- Déploiement de Granted sur AWS SSO, avec chiffrement des tokens de session
- Dans GitHub Actions, approbation désormais requise avant d’exécuter les workflows des contributeurs externes
Enseignements pour les autres équipes
- Le simple fait que l’installation npm puisse exécuter du code arbitraire constitue en soi une surface d’attaque
- Il faut activer
ignore-scripts=true et ne mettre en liste blanche que les packages réellement nécessaires
pnpm minimumReleaseAge permet de retarder l’installation des nouveaux packages
- La protection de branche et le déploiement via OIDC sont des mesures de sécurité indispensables
- Il ne faut pas stocker d’identifiants longue durée sur les machines locales ; les déploiements doivent passer uniquement par la CI
- Le bruit des alertes Slack s’est révélé être la clé de la détection
Dimension humaine
- Le développeur infecté n’est pas en faute : il a été compromis pour avoir simplement exécuté
npm install
- Pendant l’attaque, il a aussi été constaté que le compte concerné avait automatiquement ajouté en favori des centaines de dépôts aléatoires
- L’incident révèle non pas une erreur individuelle, mais une vulnérabilité structurelle de l’écosystème
Indicateurs récapitulatifs
- Délai entre l’infection initiale et la première attaque : environ 2 heures
- Durée de maintien de l’accès par l’attaquant : 17 heures
- Durée des actions destructrices : 10 minutes
- 5 minutes jusqu’à la détection, 4 minutes jusqu’au blocage
- 7 heures jusqu’à la restauration complète
- Dépôts clonés : 669 / branches affectées : 199 / PR fermées : 42
Ressources de référence
- Socket.dev : Shai-Hulud Strikes Again V2
- Rapports d’analyse de PostHog, Wiz, Endor Labs et HelixGuard
- Documentation npm Trusted Publishers, pnpm
onlyBuiltDependencies, minimumReleaseAge, Granted
Aucun commentaire pour le moment.