17 points par GN⁺ 2025-11-25 | 5 commentaires | Partager sur WhatsApp
  • Sur le registre NPM, plus de 1 000 composants ont été infectés en quelques heures selon la même méthode, et de nouvelles versions contenant du code malveillant ont été publiées
  • Les paquets malveillants se faisaient passer pour un script d’installation du runtime Bun, en ajoutant setup_bun.js et bun_environment.js obfusqué ; à l’exécution, ils utilisaient TruffleHog pour voler des identifiants locaux
  • Les informations sensibles collectées, dont des tokens AWS/GCP/Azure, GitHub et NPM, étaient exfiltrées via un runner GitHub Action nommé SHA1HULUD
  • Le script malveillant exécutait automatiquement npm publish afin d’assurer une auto-réplication de type ver, ce qui a abouti à l’infection de plus de 27 000 dépôts GitHub
  • Le cas est considéré comme un nouvel exemple mettant en lumière la menace sur la sécurité de la supply chain dans tout l’écosystème open source

Vue d’ensemble de l’attaque

  • Le 24 novembre 2025, HelixGuard a détecté sur le registre NPM plus de 1 000 paquets infectés en quelques heures selon le même mode opératoire
    • Les nouvelles versions se présentaient comme ajoutant le runtime Bun et incluaient le script preinstall: node setup_bun.js
    • Le fichier bun_environment.js, distribué avec elles, contenait un code malveillant obfusqué qui téléchargeait et exécutait TruffleHog
  • TruffleHog scannait l’environnement local pour voler des tokens NPM, identifiants AWS/GCP/Azure et variables d’environnement
  • Les informations dérobées étaient exfiltrées en créant un runner GitHub Action SHA1HULUD, puis via un dépôt GitHub portant la description Sha1-Hulud: The Second Coming.
  • HelixGuard estime que cette attaque pourrait être l’œuvre du même acteur que dans l’incident « Shai-Hulud » survenu en septembre 2025

Analyse du fonctionnement du code malveillant

  • L’analyse du paquet @asyncapi/specs, pris comme exemple, montre que la version publiée sur NPM était infectée, alors que le dépôt source sur GitHub restait sain
  • L’attaquant a modifié package.json pour ajouter setup_bun.js, puis a configuré ce script pour appeler bun_environment.js
  • bun_environment.js est un fichier JavaScript fortement obfusqué de plus de 10 Mo, dont les fonctions principales sont les suivantes
    • collecte d’identifiants cloud et de tokens à partir des variables d’environnement
    • scan de secrets avec TruffleHog
    • exfiltration de données via GitHub Actions
  • Le code modifiait aussi package.json pour y injecter l’infection, puis exécutait automatiquement npm publish afin d’assurer une propagation de type ver

Infection de GitHub et exfiltration de données

  • Le script malveillant créait le fichier .github/workflows/formatter_123456789.yml et enregistrait le runner SHA1HULUD
  • Ce workflow empaquetait les secrets du dépôt dans un fichier actionsSecrets.json, encodé en Base64 deux fois
  • Il créait ensuite un dépôt GitHub au nom aléatoire avec la description Sha1-Hulud: The Second Coming. pour y téléverser les données
  • HelixGuard a confirmé que plus de 27 000 dépôts GitHub avaient été infectés
  • Parmi les secrets dérobés figuraient des identifiants de nombreux services, dont AWS_ACCESS_KEY_ID, SLACK_WEBHOOK_URL, CODECOV_TOKEN et WEBFLOW_TOKEN

Liste des paquets infectés

  • HelixGuard a signalé l’infection de centaines de paquets NPM
    • Parmi eux, des paquets d’organisations majeures comme @asyncapi, @ensdomains, @posthog, @zapier, @postman et @voiceflow
    • Plusieurs versions de chaque paquet ont été touchées, par exemple @asyncapi/specs@6.8.2 et @postman/csv-parse@4.0.5
  • La plupart de ces paquets usurpaient l’apparence de projets open source légitimes, avec du code malveillant injecté dans le processus de déploiement automatisé

Enjeux de sécurité

  • Cette attaque illustre comment des failles de sécurité de la supply chain peuvent être exploitées pour contaminer à grande échelle l’écosystème open source
  • Elle met en évidence la nécessité de renforcer la sécurité de l’ensemble de l’infrastructure de développement, notamment autour de NPM, GitHub et des identifiants cloud
  • HelixGuard recommande d’interrompre immédiatement l’installation des paquets infectés et de révoquer sans délai les tokens et identifiants concernés

5 commentaires

 
ahwjdekf 2025-11-27

L’écosystème JS est vraiment un bordel sans nom, comme le dit le thread.

 
developerjhp 2025-11-25

J’ai créé un script de scanner en temps réel.

Dans le chemin du dépôt suspect,
exécutez npx sha1-hulud-scanner.

Code source : https://github.com/developerjhp/sha1-hulud-scanner

 
GN⁺ 2025-11-25
Avis Hacker News
  • Petit conseil : mieux vaut utiliser PNPM plutôt que NPM
    PNPM 10.x bloque plusieurs vecteurs d’attaque
    1️⃣ Par défaut, il n’exécute pas les scripts post-install et exige une approbation manuelle
    2️⃣ Il peut être configuré pour n’installer un paquet qu’après un certain délai suivant la publication d’une nouvelle version (par exemple 4 jours)
    NPM est trop instable pour un environnement CLI de production
    Il vaut mieux limiter les clés d’éditeur au strict minimum, les lier à des paquets précis et restreindre les IP à celles des runners CI/CD
    Ne gardez pas de clé de publication en local ; si besoin, envisagez OIDC Trusted Publisher ou un accès par jeton

    • NPM donne l’impression d’être le résultat d’une énorme accumulation de dette technique
      Rien que pour les lockfiles, ils s’y sont repris au moins cinq fois, et ce n’est toujours pas parfait
      À voir la structure et l’historique des commits, on sent que l’équipe fait de gros efforts pour améliorer les choses, mais avec l’impression d’être partie d’un trou beaucoup trop profond
      Il ne détecte toujours pas les EOF prématurés pendant les transferts de fichiers et laisse des fichiers incomplets dans le cache, ce qui fait perdre un temps fou sur les connexions lentes à cause des échecs de mise à jour
    • Je préfère l’approche de gestion dynamique des secrets de HashiCorp Vault / OpenBao
      C’est plus complexe au départ, mais cela permet de gérer les secrets sous forme de bail (lease)
      Un bail peut être créé pour chaque build CI puis révoqué automatiquement à la fin, avec prise en charge du TTL et de la rotation automatique
      Cela permet de masquer les identifiants longue durée et de n’émettre que des jetons à courte durée de vie au moment du build
      Grâce à ce type d’attaque, de vraies discussions sur la sécurité s’ouvrent enfin dans les entreprises, et c’est positif
    • Il suffit d’utiliser npm ci
      Comme seules les versions indiquées dans package-lock.json sont installées, cela réduit le risque d’attaque lié aux mises à jour automatiques
      L’important est de ne faire que des mises à jour intentionnelles
    • Dans l’écosystème Python, on peut obtenir une protection similaire avec l’option pip install --only-binary=:all:
      Cela bloque complètement les distributions source et n’installe que des wheel
      En contrepartie, cela peut imposer des contraintes de version
      Dans uv, l’option --exclude-newer permet d’imiter la fonctionnalité de « durée minimale avant installation » de PNPM
    • J’ai récemment lu un billet sur le dependency cooldown, et je m’y retrouve beaucoup
      Je fige toutes mes dépendances et j’examine manuellement les alertes dependabot
      Je me demande encore si c’est excessif ou simplement une bonne habitude
  • Il y a justement aujourd’hui un article très pertinent : “We should all be using dependency cooldowns”
    Les mises à jour automatiques de dépendances peuvent être plus dangereuses qu’une vulnérabilité d’un jour
    Il est bien plus difficile de faire marche arrière sur un paquet infecté déjà propagé dans des milliers de lockfiles

    • À mon avis, mieux vaut ne mettre à jour qu’en cas de besoin
      Si tout fonctionne bien, il n’y a pas de raison d’y toucher
    • Mais même dans ce cas, il faut bien que quelqu’un corrige les bugs ; si tout le monde utilise un cooldown, on risque de faire du sur-place
    • Avec uv pour Python, on peut obtenir un effet similaire avec la commande uv lock --exclude-newer $(date --iso -d "24 hours ago")
      La discussion correspondante est dans l’issue #14992
    • C’est aussi très simple avec npm-check-updates
      La commande npx npm-check-updates -c 7 permet de définir un cooldown de 7 jours
      Voir la documentation npm-check-updates
    • Je ne suis pas d’accord avec cette logique
      Un cooldown peut allonger le temps de propagation d’une vulnérabilité 0-day
      Si tout le monde applique le même cooldown, cela ne fait que retarder la découverte
  • Je suis le cofondateur de PostHog
    Nous avons été touchés par cette attaque
    Les versions infectées sont posthog-node 4.18.1, 5.13.3, 5.11.3 / posthog-js 1.297.3 / posthog-react-native 4.11.1 / posthog-docusaurus 2.0.6
    Nous avons remplacé toutes les clés et tous les mots de passe, et publié de nouvelles versions
    Nous analysons actuellement la cause et publierons des mises à jour sur status.posthog.com

    • Je recommande de configurer une alerte si une nouvelle release de paquet n’est pas liée à une exécution CI/CD
    • Je me demande si le JS infecté a réellement eu un impact sur des utilisateurs finaux
      Si un site web a déployé la version compromise, j’aimerais savoir si ses visiteurs ont subi un préjudice
    • Si la cause n’est pas encore connue, il est possible que l’attaque soit toujours en cours de propagation
    • Une nouvelle version pourrait à son tour être infectée ; je me demande donc pourquoi on devrait faire confiance à celle-ci cette fois
    • Heureusement que la mise à jour est plus visible ici que dans l’annonce sur Twitter. Bon courage pour la remise en état
  • Question sérieuse : est-ce vraiment raisonnable de démarrer un nouveau projet avec Node
    Je construis un frontend SaaS avec Astro, et chaque mise à jour de dépendance m’inquiète
    L’absence de sécurité dans l’écosystème npm me paraît beaucoup trop grave

    • Le problème, ce n’est pas Node ni JS, c’est le modèle de packaging
      Même des écosystèmes comme Rust, qui dépendent d’innombrables sous-paquets, finiront par connaître la même chose
      Des langages comme C, C++, ou Odin, sans gestionnaire de paquets central, font peut-être au contraire un choix plus judicieux du point de vue sécurité
    • Je pense que le problème vient plus de npm lui-même que de Node
      Ces derniers temps, je fais davantage confiance à JSR de Deno
      Les paquets basés sur JSR sont aussi publiés sur npm, et il existe également des paquets spécifiques à Deno
      Par exemple, Lume m’a fait une bonne impression comme SSG lent mais stable
    • Ce n’est pas propre à Node
      npm est simplement le plus grand registre, donc la cible la plus rentable pour les attaquants
      Cela pourrait tout aussi bien arriver sur RubyGems ou Cargo
    • Dire qu’il faut éviter Node me semble excessif
      C’est juste l’écosystème le plus utilisé, donc celui qui concentre les attaques
      Il suffit de gérer ses dépendances avec prudence et d’éviter de mettre à jour tous les jours
    • Nous avons développé notre plateforme d’analyse de sécurité produit en PHP
      L’avantage, c’est qu’il n’y a pas besoin de plus de 100 dépendances juste pour rendre une page
      Voir le lien du projet
  • En ce moment, je fais tout mon développement uniquement dans des conteneurs Podman
    Je n’exécute du code non lu que dans un environnement isolé
    Ce n’est pas parfait, mais je considère que c’est une habitude de sécurité minimale

    • La plupart des gens ne voient jamais de problème dans 99,99 % des cas, donc leur perception du risque s’émousse
      En pratique, la sécurité est souvent un domaine délégué aux spécialistes, ce qui rend le changement difficile
    • Les paquets npm ont des arbres de dépendances bien trop profonds ; je me demande comment l’isolation par conteneur fonctionne dans ce cas
    • J’aimerais connaître une méthode concrète pour gérer un paquet npm comme le SDK PostHog à l’intérieur d’un conteneur
    • Podman est plus sûr que Docker, et si nécessaire on peut même envisager une isolation supplémentaire avec QEMU
    • Moi, je vais jusqu’à me connecter en SSH avec un autre utilisateur local et à développer dans tmux
  • Il y a 12 ans, NPM est déjà tombé complètement hors service une fois
    À l’époque, ce n’était qu’un projet open source, mais aujourd’hui il appartient à Microsoft
    Quand on est l’une des plus grandes entreprises du monde, on devrait pouvoir régler ce genre de problème, non ?
    Pourtant, pas grand-chose n’a vraiment changé

    • Microsoft n’arrive même pas à gérer correctement Windows
      Tout ce qui ne rapporte pas directement via les licences entreprise est laissé de côté
      C’est pour ça que Windows 11 ressemble à un produit de pur marketing
  • Nous sommes actuellement en train de surveiller l’activité de l’attaque et de mettre à jour la liste des paquets infectés sur le blog Wiz
    Nous faisons l’ingénierie inverse du payload malveillant et partagerons nos conclusions d’ici quelques heures

  • Le chat « Talk to a human » de PostHog m’a agacé, car il répondait en fait avec un robot
    Le lien d’assistance d’urgence n’était pas indiqué correctement
    Donc je repose la question — quelles versions faut-il éviter ?

    • Je suis cofondateur. C’est déjà indiqué dans le fil principal et sur status.posthog.com
      Les versions infectées sont posthog-node 4.18.1, 5.13.3, 5.11.3 / posthog-js 1.297.3 / posthog-react-native 4.11.1 / posthog-docusaurus 2.0.6
      Une mise à jour vers la dernière version est sûre
    • J’ai reçu la même liste de versions sur le canal Slack
  • Je me demande pourquoi ce genre de chaos autour des paquets arrive toujours dans l’écosystème Node
    Je ne comprends pas pourquoi cette communauté considère comme une bonne pratique d’ingénierie les hooks d’installation complexes et les mises à jour automatiques
    Je comprends mieux pourquoi le créateur de Node a fini par partir

    • Node, c’est un peu le nouveau PHP
      Un écosystème immense, centré sur les développeurs débutants, peu sensibilisé à la sécurité, et où même la moindre fonctionnalité dépend d’une bibliothèque
    • Un écosystème sérieux devrait avoir de vrais mainteneurs de paquets
      Comme dans Debian, il faudrait des responsables de confiance qui valident les paquets, mais la communauté JS rejette cela comme du gatekeeping
      C’est pour ça que ce genre de crise se répète
    • Rabaisser les autres pour se sentir supérieur ne procure qu’une satisfaction passagère
      Avec cette attitude, rien ne changera
  • C’est un peu hors sujet, mais je me demande qui est HelixGuard
    Leur site web est mauvais et on trouve très peu d’informations
    Ils disent avoir des plateformes d’échange crypto comme clients, ce qui paraît suspect

 
laeyoung 2025-11-25

2️⃣ Il est possible de configurer l’installation pour qu’elle n’ait lieu qu’après un certain délai suivant le déploiement d’une nouvelle release (par exemple, 4 jours).

C’est une fonctionnalité vraiment excellente. Même Google publie parfois sur NPM des versions buguées qui ne fonctionnent pas, donc il m’arrive de me demander si le bug vient de chez moi et de paniquer un peu.