Le malware sur le thème de Shai-Hulud découvert dans la bibliothèque d’entraînement IA PyTorch Lightning | Semgrep
(semgrep.dev)- Les versions 2.6.2 et 2.6.3 de
lightningsur PyPI, publiées le 30 avril 2026, ont été exploitées dans une attaque de supply chain, et un simplepip install lightningpouvait déclencher l’exécution d’un répertoire caché_runtimeet d’une charge utile JavaScript obfusquée - La charge utile malveillante s’exécute automatiquement à l’import du module et dérobe des identifiants, des jetons d’authentification, des variables d’environnement et des secrets cloud, tout en essayant aussi de contaminer des dépôts GitHub
- Cette attaque a pour point d’entrée PyPI, mais la propagation du ver s’effectue via npm ; si des identifiants de publication npm sont trouvés, il injecte le dropper
setup.mjsetrouter_runtime.jsdans les packages publiables, puis republie une version de patch - L’exfiltration des données utilise quatre canaux parallèles — POST HTTPS, dead drop par recherche de commits GitHub, dépôt GitHub public contrôlé par l’attaquant et push direct vers le dépôt de la victime — et laisse comme indicateurs le préfixe de commit
EveryBoiWeBuildIsAWormyBoiet la description de dépôt"A Mini Shai-Hulud has Appeared" - Le malware implante le hook
SessionStartde.claude/settings.jsondans Claude Code et une tâcherunOn: folderOpendans.vscode/tasks.jsonpour VS Code, afin d’exécuter le dropper à chaque ouverture du dépôt ; toute machine ayant importé le package malveillant pendant la période concernée doit être considérée comme totalement compromise
Packages affectés et procédure de vérification
lightningest un framework de deep learning souvent présent dans l’arbre de dépendances des équipes qui construisent des classifieurs d’images, font du fine-tuning de LLM, exécutent des modèles de diffusion ou développent des outils de prévision de séries temporelles-
Packages affectés
lightningversion2.6.2lightningversion2.6.3
-
Procédure de vérification pour les clients Semgrep
- Si vous n’avez pas exécuté de scan de projet récemment, vous devez lancer un nouveau scan
- Vous pouvez vérifier sur la page advisories si le projet a récemment installé cette version du package
- Vous pouvez consulter les correspondances dans le dependency filter ; si “No matching dependencies” s’affiche, cela signifie que le projet n’utilise pas activement la dépendance malveillante
- S’il existe des correspondances, vous devez auditer dans le dépôt les fichiers inattendus dans les répertoires
.claude/et.vscode/mentionnés dans les indicateurs de compromission ci-dessous - Vous devez remplacer les jetons GitHub, identifiants cloud et clés API qui ont pu se trouver dans l’environnement affecté
- Des conseils généraux sur la réponse aux attaques de supply chain et les périodes d’attente sont donnés dans $foo compromised in $packagemanager et Attackers are Still Coming for Security Companies
Structure de propagation de PyPI vers npm
- Contrairement à mini Shai-Hulud, qui visait directement npm, le point d’entrée de cette attaque est PyPI
- La charge utile malveillante reste en JavaScript, et la propagation du ver passe par npm
- Si le code malveillant exécuté trouve des identifiants de publication npm, il injecte le dropper
setup.mjsetrouter_runtime.jsdans tous les packages publiables avec ce jeton - Il configure ensuite
scripts.preinstallpour exécuter le dropper, augmente la version de patch, puis republie le package - Les développeurs en aval qui installent ces packages exécutent alors l’ensemble du code malveillant sur leur machine, ce qui entraîne le vol de jetons et l’infection par le ver de packages
Méthodes d’exfiltration des données
- La fonctionnalité de vol partage les mécanismes et la conception de la campagne précédente Mini Shai-Hulud, et utilise quatre canaux parallèles pour faire sortir les données même si certaines voies sont bloquées
- L’attaque reprend le thème Shai-Hulud, notamment avec la création d’un dépôt public nommé
EveryBoiWeBuildIsaWormBoi - La structure des indicateurs de l’attaque correspond à celle de la campagne précédente mini Shai-Hulud, mais les messages de commit malveillants utilisent le préfixe
EveryBoiWeBuildIsAWormyBoi, ce qui les distingue de l’attaque Mini Shai-Hulud d’origine -
Transmission C2 via HTTPS POST
- Les données volées sont immédiatement envoyées par POST à un serveur contrôlé par l’attaquant via le port 443
- Le domaine et le chemin sont stockés dans la charge utile sous forme de chaînes chiffrées afin de compliquer l’analyse statique
-
Dead drop via recherche de commits GitHub
- Le malware interroge en boucle l’API de recherche de commits GitHub pour trouver des messages de commit préfixés par
EveryBoiWeBuildIsAWormyBoi - Les messages de commit transportent un jeton doublement encodé en Base64 au format
EveryBoiWeBuildIsAWormyBoi:<base64(base64(token))> - Le jeton décodé est ensuite utilisé pour authentifier un client Octokit pour les opérations ultérieures
- Le malware interroge en boucle l’API de recherche de commits GitHub pour trouver des messages de commit préfixés par
-
Dépôt GitHub public contrôlé par l’attaquant
- Un nouveau dépôt public est créé avec un nom de mot aléatoire tiré de Dune et la description
"A Mini Shai-Hulud has Appeared" - Cette description est directement recherchable sur GitHub
- Les identifiants volés y sont commités sous la forme
results/results-<timestamp>-<n>.json; ils sont encodés en Base64 via l’API, mais leur contenu interne reste du JSON ordinaire - Les fichiers dépassant 30 MB sont découpés en fragments numérotés
- Les messages de commit utilisent
chore: update dependenciescomme camouflage
- Un nouveau dépôt public est créé avec un nom de mot aléatoire tiré de Dune et la description
-
Push direct vers le dépôt de la victime
- Si le malware obtient un jeton serveur GitHub
ghs_, il pousse directement les données volées sur toutes les branches deGITHUB_REPOSITORYde la victime
- Si le malware obtient un jeton serveur GitHub
Cibles du vol
- Le malware vise des identifiants présents dans les fichiers locaux, l’environnement, les pipelines CI/CD et chez les fournisseurs cloud
-
Système de fichiers
- Il scanne plus de 80 chemins de fichiers d’identifiants pour y trouver des jetons
ghp_,gho_etnpm_ - Il traite jusqu’à 5 MB par fichier
- Il scanne plus de 80 chemins de fichiers d’identifiants pour y trouver des jetons
-
Shell et variables d’environnement
- Il exécute
gh auth token - Il vide toutes les variables d’environnement de
process.env
- Il exécute
-
GitHub Actions
- Sur les runners Linux, il vide la mémoire du processus
Runner.Workerà l’aide du Python intégré - Il extrait tous les secrets marqués
"isSecret":trueainsi queGITHUB_REPOSITORYetGITHUB_WORKFLOW
- Sur les runners Linux, il vide la mémoire du processus
-
Organisations GitHub
- Il vérifie les scopes du jeton,
repoetworkflow - Il parcourt les secrets d’organisation GitHub Actions
- Il vérifie les scopes du jeton,
-
AWS
- Il tente d’appeler
sts:GetCallerIdentityvia des variables d’environnement, des profils~/.aws/credentials, IMDSv2169.254.169.254et ECS169.254.170.2 - Il énumère et récupère toutes les valeurs de Secrets Manager ainsi que les paramètres SSM
- Il tente d’appeler
-
Azure
- Il utilise
DefaultAzureCredentialpour énumérer les abonnements et accéder aux secrets Key Vault
- Il utilise
-
GCP
- Il s’authentifie avec
GoogleAuth - Il énumère et récupère tous les secrets de Secret Manager
- La portée visée couvre les environnements de développement locaux, les runners CI et les trois principaux fournisseurs cloud
- Toute machine ayant importé le package malveillant pendant la période affectée doit être considérée comme totalement compromise
- Il s’authentifie avec
Persistance via les outils de développement
- Une fois introduit dans le dépôt, le malware cible Claude Code et VS Code, des outils de développement courants, pour y implanter des hooks de persistance
-
Claude Code
- Le malware écrit dans
.claude/settings.json, le fichier de configuration Claude Code du dépôt, un hookSessionStartavecmatcher: "*" - Le hook pointe vers
node .vscode/setup.mjs - Il s’exécute à chaque fois qu’un développeur ouvre Claude Code dans le dépôt infecté, sans nécessiter d’autre usage d’outil ni action de l’utilisateur au-delà du démarrage de session
- Le malware écrit dans
-
VS Code
- Pour cibler les utilisateurs de VS Code, il implante dans
.vscode/tasks.jsonune tâcherunOn: folderOpen node .claude/setup.mjss’exécute à chaque ouverture du dossier du projet
- Pour cibler les utilisateurs de VS Code, il implante dans
-
Dropper
setup.mjs- Les deux hooks appellent
setup.mjs, un bootstrapper autonome du runtime Bun - Si Bun n’est pas installé, il télécharge discrètement
bun-v1.3.13depuis les releases GitHub - Il gère Linux x64, Linux arm64, Linux musl, macOS x64, macOS arm64, Windows x64 et Windows arm64
- Il exécute ensuite la charge utile complète
.claude/router_runtime.js, de 14.8 MB, puis nettoie/tmp
- Les deux hooks appellent
-
Workflow GitHub Actions malveillant
- Si le malware possède un jeton GitHub avec droit d’écriture, il pousse dans le dépôt de la victime un workflow nommé
Formatter - À chaque push, il vide tous les secrets du dépôt via
${{ toJSON(secrets) }} - Il téléverse le résultat sous forme d’artefact Actions téléchargeable nommé
format-results - Les Actions sont épinglées à des SHA de commit spécifiques pour sembler légitimes
- Les dépôts ayant reçu le package
lightninginfecté en CI et disposant d’un jeton avec droits d’écriture doivent auditer ces fichiers
- Si le malware possède un jeton GitHub avec droit d’écriture, il pousse dans le dépôt de la victime un workflow nommé
Indicateurs de compromission
-
Indicateurs recherchables
- Les messages de commit préfixés par
EveryBoiWeBuildIsAWormyBoiservent de transporteurs de jetons pour le dead drop et peuvent être trouvés via la recherche de commits GitHub - Les dépôts GitHub dont la description est
"A Mini Shai-Hulud has Appeared"sont des dépôts d’exfiltration contrôlés par l’attaquant et peuvent être recherchés directement
- Les messages de commit préfixés par
-
Packages
lightning@2.6.2lightning@2.6.3
-
Fichiers et artefacts système
_runtime/start.py: chargeur Python qui initialise la charge utile à l’import_runtime/router_runtime.js: charge utile JavaScript obfusquée, correspondant au runtime Bun de 14.8 MB_runtime/: répertoire ajouté dans les versions malveillantes du package.claude/router_runtime.js: copie du malware injectée dans le dépôt de la victime.claude/settings.json: configuration du hook Claude Code injectée dans le dépôt de la victime.claude/setup.mjs: dropper injecté dans le dépôt de la victime.vscode/tasks.json: tâche d’exécution automatique VS Code injectée dans le dépôt de la victime.vscode/setup.mjs: dropper injecté dans le dépôt de la victime
Aucun commentaire pour le moment.