3 points par GN⁺ 2025-10-31 | 2 commentaires | Partager sur WhatsApp
  • Il a été confirmé que plus de 100 paquets malveillants destinés au vol d’identifiants ont été publiés sur le dépôt NPM sans être détectés depuis août, et qu’ils ont été téléchargés au total plus de 86 000 fois
  • La société de sécurité Koi rapporte qu’une campagne d’attaque baptisée PhantomRaven a distribué 126 paquets malveillants en abusant de la fonctionnalité Remote Dynamic Dependencies (RDD) de NPM
  • Le RDD est un mécanisme qui permet à un paquet de télécharger dynamiquement du code de dépendance depuis des domaines non fiables, ce qui empêche sa détection par les outils d’analyse statique
  • Les attaquants ont exploité cette fonctionnalité pour télécharger du code malveillant via des connexions HTTP, tandis que les métadonnées des paquets affichaient « 0 Dependencies », empêchant les développeurs et les scanners de sécurité de s’en apercevoir
  • Cette faiblesse structurelle met en évidence les limites de la gestion de la sécurité dans l’écosystème NPM ainsi que les risques des mécanismes d’installation automatique

Propagation de paquets malveillants dans le dépôt NPM

  • Des attaquants ont exploité une faiblesse structurelle du dépôt de code NPM pour publier, depuis août, plus de 100 paquets destinés au vol d’identifiants
    • La plupart de ces paquets ont été diffusés sans être détectés, avec un total cumulé de plus de 86 000 téléchargements
  • La société de sécurité Koi a nommé cette attaque la campagne PhantomRaven et a analysé l’exploitation d’une fonctionnalité spécifique de NPM
    • Selon Koi, sur les 126 paquets malveillants, environ 80 étaient encore présents sur NPM au moment de la rédaction de l’article

Structure vulnérable de Remote Dynamic Dependencies (RDD)

  • Le RDD est une fonctionnalité qui permet à un paquet de télécharger dynamiquement du code de dépendance depuis des sites externes
    • En temps normal, les dépendances sont récupérées depuis l’infrastructure de confiance de NPM, mais le RDD autorise aussi des téléchargements via des connexions non chiffrées comme HTTP
  • Les attaquants de PhantomRaven ont utilisé cette fonctionnalité pour configurer le téléchargement de code depuis des URL malveillantes (ex. : http://packages.storeartifact.com/npm/unused-imports)
    • Ces dépendances sont invisibles pour les développeurs comme pour les scanners de sécurité, et les informations du paquet affichent « 0 Dependencies »
  • En raison du mécanisme d’installation automatique de NPM, ce code de dépendance « invisible » est exécuté automatiquement

Limites de détection des outils de sécurité

  • Oren Yomtov de Koi a déclaré que « PhantomRaven est un cas qui exploite avec sophistication les angles morts des outils de sécurité existants »
    • Le RDD n’est pas détecté par les outils d’analyse statique
  • Cela a permis aux attaquants de contourner les vérifications de sécurité et de distribuer du code malveillant

Facteurs de vulnérabilité supplémentaires

  • Koi explique que les dépendances téléchargées via le RDD sont retéléchargées depuis le serveur des attaquants à chaque installation
    • En l’absence de cache ou de gestion de versions, il existe une possibilité que du code malveillant différent soit injecté selon le moment de l’installation, même pour un même paquet
  • Cette structure de téléchargement dynamique complique la vérification de l’intégrité des paquets

Structure et contexte de NPM

  • NPM est un gestionnaire de paquets pour JavaScript, maintenu par npm, Inc., une filiale de GitHub
    • Il s’agit du gestionnaire de paquets par défaut de Node.js et il se compose d’un client en ligne de commande et du npm registry
    • Le registry stocke des paquets publics ainsi que des paquets privés payants, consultables via le site web
  • Cet incident est présenté comme un exemple montrant que la structure de gestion automatique des dépendances de NPM peut être détournée à des fins d’attaque

Autres mentions

  • En fin d’article, il est mentionné qu’il faudrait bloquer l’exécution inutile de JavaScript
    • Toutefois, cette attaque est soulignée comme un cas où même du code JavaScript indispensable a été détourné

2 commentaires

 
developerjhp 2025-11-25

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

Depuis le chemin du dépôt suspect,
npx sha1-hulud-scanner
il suffit de le saisir.

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

 
GN⁺ 2025-10-31
Avis Hacker News
  • En ce moment, j’ai configuré un alias pour exécuter la commande npm dans un conteneur Docker
    Comme ça, mes variables d’environnement ne sont pas exposées, il n’a pas accès aux fichiers hors du répertoire courant, ni aux fichiers de configuration comme .bashrc
    Référence : Run tools inside Docker

    • Ça ressemble à un sandboxing excessif. De toute façon, npm télécharge du code arbitraire qui sera exécuté immédiatement
      À la place, je recommande pnpm. Par défaut, il n’exécute pas les scripts de cycle de vie et permet de mettre en liste blanche ceux à autoriser
    • Diaboliser les scripts post-install ne donne qu’une fausse impression de sécurité
      Si on veut une vraie protection, il faut sandboxer non seulement l’installation mais aussi toute l’exécution
      Bloquer uniquement les post-install, comme on le fait maintenant, n’est qu’une demi-mesure. Les attaques sur la chaîne d’approvisionnement deviennent de plus en plus dangereuses
    • Il y a trop de vecteurs d’attaque. Avec une intention malveillante, on peut typosquatter le nom d’un plugin populaire ou d’un LSP et faire exécuter automatiquement du code au lancement de l’éditeur
      Si neovim ou vscode est compromis, il peut déjà faire des choses très dangereuses avec les droits de l’utilisateur
    • J’utilise sandbox-run
      Un simple alias marche pour node/npm, mais il est difficile à appliquer à d’autres programmes, puisqu’il faut monter dans le conteneur les ressources nécessaires
    • Mais au final, on peut quand même télécharger un paquet malveillant, non ? La dépendance elle-même peut être compromise
  • Je me le demandais depuis longtemps : pourquoi les gens exécutent npm sur leur système comme si de rien n’était ?
    Quand on est habitué aux builds reproductibles avec make, c’est choquant de voir npm télécharger quelque chose de différent à chaque fois et produire des résultats différents
    Je trouvais déjà étrange de lier même la génération du CSS à des dépendances npm. J’ai donc essayé de figer tout l’environnement npm dans Docker, mais ça semble être un combat perdu d’avance

    • Aujourd’hui, tous les gestionnaires de paquets fonctionnent plus ou moins comme ça. maven, nuget, pip, npm, c’est pareil
      Si on dépendait encore des gestionnaires de paquets des distributions comme avant, l’écosystème rapide qu’on a aujourd’hui serait impossible
      Cela dit, de nouveaux gestionnaires de paquets plus sécurisés apparaissent. Critiquer l’outil sans comprendre la raison de son existence n’est pas juste
    • Le développement front-end ressemble à un Far West du “trust me bro”. Avec l’évolution des navigateurs, on a l’impression que tout a été assemblé au ruban adhésif
    • Si tu as figé npm dans Docker, j’aimerais savoir si tu validais cet environnement après chaque mise à jour des dépendances
      En réalité, npm et pnpm figent déjà les dépendances par défaut avec des fichiers lock
    • C’est un problème créé par la facilité et le faible coût de “npm install thing
      Beaucoup d’open source se retrouve rempli de code écrit pour le CV plutôt que pour la qualité, et finit par servir à fabriquer des traqueurs publicitaires de géants du web ou des applis de portefeuille
  • npm install ne se contente pas de télécharger un paquet, il exécute du code
    Les hooks preinstall, install et postinstall de package.json sont réellement exécutés
    Quelle raison légitime peut justifier l’exécution de commandes arbitraires pendant l’installation ?
    Rapport lié : PhantomRaven npm malware
    Autre cas : blog Socket.dev

    • En réalité, cette structure existait déjà dans d’anciens gestionnaires de paquets (DEB, RPM)
      Par exemple, les paquets du noyau Linux exécutent des scripts post-install pour régénérer l’initramfs, mettre à jour GRUB, etc.
      La plupart des paquets DEB/RPM contiennent ce type de scripts. C’est donc un problème de conception en soi
    • Le problème, c’est que npm permet à n’importe qui de publier un paquet
      Les distributions Linux ont un système de mainteneurs de confiance et peuvent même établir directement une racine de confiance basée sur PGP
      En revanche, npm, pip, rubygems, cargo, etc. ne sont au fond qu’une version sophistiquée de “curl | bash
    • Par exemple, le projet Mediasoup est une bibliothèque de streaming écrite en C++ qui compile directement les sources à l’installation
      Ce type de build post-install était nécessaire pour réduire la charge de maintenance
    • Swift Package Manager exécute lui aussi réellement le fichier Package.swift
      Mais j’ai entendu dire qu’il est fortement sandboxé, ce qui rend l’abus difficile
      Référence : documentation SwiftPM, PackageDescription
    • À noter que pnpm v10 désactive désormais tous les scripts de cycle de vie par défaut, et demande une autorisation explicite de l’utilisateur
      Discussion liée
  • Quand on voit les attaques récentes contre npm, on se demande si développer avec npm est encore sûr
    À chaque fois que je démarre un projet React, des centaines de paquets s’installent, sans que je sache vraiment ce qu’ils font
    Côté back-end, on installe explicitement uniquement les paquets nécessaires, mais le front-end ressemble à une boîte de Pandore de vulnérabilités

    • En réalité, tous les écosystèmes de langage sont similaires. C’est juste que npm est le plus gros et fait plus souvent les gros titres
    • J’ai installé jj en Rust : 470 paquets. wan2gp en Python : 211 paquets. C’est partout pareil
    • L’écosystème JavaScript est structurellement vulnérable aux attaques
      Comme dans l’affaire xz, chaque dépendance repose sur des individus pris au hasard, et il faut croire qu’ils ne se feront pas piéger par de l’ingénierie sociale
    • Moins il y a de dépendances, mieux c’est. Zéro dépendance, c’est la perfection. Voilà la vraie victoire
    • À noter que PyPI n’est pas sûr non plus. Il y a déjà eu des cas où du code malveillant a été injecté dans des paquets légitimes via le piratage de GitHub Actions
  • Chaque fois que je développe avec des frameworks comme Angular ou Vue, ça m’inquiète
    Quand je vois les milliers de dépendances dans node_modules, j’ai l’impression d’un désastre annoncé
    Il suffit qu’un développeur open source se fasse piéger par phishing pour que tout soit compromis
    L’écosystème JavaScript est fondamentalement cassé. Une simple faute de frappe peut exposer à une attaque sur la chaîne d’approvisionnement
    C’est aussi possible avec NuGet ou Maven, mais là-bas il y a une bibliothèque standard plus riche, donc moins de dépendances et davantage de contrôle

    • Go utilise des URL de dépôt plutôt que des noms de paquet, ce qui réduit le typosquatting
      Ce n’est pas parfait, mais c’est déjà un cran au-dessus
    • Deno résout ce problème. C’est un problème structurel de Node.js / npm
  • Sur les 86 000 téléchargements, il est probable que la plupart ne viennent pas de vrais utilisateurs mais de scanners automatisés ou de bots
    Quand on publie une nouvelle version, on voit parfois des centaines de téléchargements en un ou deux jours, sans qu’il s’agisse forcément d’humains
    Autrement dit, il se peut qu’il n’y ait presque aucun utilisateur réellement infecté

    • Quand j’ai publié ma bibliothèque, elle a d’abord fait environ 300 téléchargements par semaine, puis autour de 100
      Il y a aussi beaucoup d’attaques visant des noms de paquets hallucinés par des chatbots IA. Ce n’est pas qu’une simple statistique
    • Ou alors il peut s’agir du CI zombie de quelqu’un qui continue à télécharger en boucle
    • Mais si l’attaque vise de faux noms de paquets générés par des LLM, il se peut en réalité que beaucoup de développeurs aient été infectés
  • Pour une explication plus détaillée de l’attaque, voir l’article de BleepingComputer

  • Je me demande s’il existe un moyen de détecter ou filtrer, pendant npm install, les paquets qui utilisent des URL HTTP comme dépendances
    Comme ils peuvent envoyer une charge utile différente selon le demandeur, les scanners classiques ont du mal à les détecter

  • En tant que développeur amateur, je me demande comment me préparer à ce type d’attaques de la chaîne d’approvisionnement
    Quand on suit des tutoriels connus et qu’on installe des dépendances, on finit facilement par baisser la garde sur la sécurité
    Je fais aussi tourner plusieurs services dans mon homelab, et je crains qu’un bot ne s’y infiltre. Par où commencer ?

    • Faire tourner les services séparément dans des conteneurs ou des VM permet d’isoler les dégâts
      Ce n’est pas une garantie parfaite, mais c’est bien mieux que de laisser tout le serveur se faire compromettre
    • Il faut considérer toutes les dépendances comme un risque de sécurité potentiel et ne les utiliser qu’en cas de vraie nécessité
      Copier directement uniquement le code nécessaire est aussi une bonne manière d’apprendre et une approche plus sûre
    • Il est plus sûr d’utiliser des versions populaires et publiées depuis plus d’un an. Si un problème existait, il aurait plus de chances d’avoir déjà été détecté
    • Il existe aussi des OS comme FreeBSD qui utilisent un gestionnaire de paquets système
      Avec ce type de structure, on peut établir la confiance au niveau de la distribution sans que des millions d’utilisateurs aient à tout vérifier eux-mêmes
    • Je privilégie les paquets avec plus d’un million de téléchargements hebdomadaires et sans dépendances
      Exemples : Hono, Zod
      Je suis récemment passé à Bun, qui intègre par défaut des éléments comme des pilotes de base de données ou un client S3, ce qui réduit les téléchargements supplémentaires
  • Une structure où des dépendances sont récupérées dans les hooks de cycle de vie peut devenir à tout moment un point de bascule pour une attaque
    Même si tout est sain aujourd’hui, si le propriétaire est piraté plus tard ou change d’avis, cela peut devenir du code malveillant
    Au final, ce type de hook d’installation est une conception non viable à long terme