Réserver une démo →
← Tous les insights AI News

Deux attaques npm, une différence : est-ce que quelque chose vous demande d'abord ?

Deux attaques npm, une différence : est-ce que quelque chose vous demande d'abord ?

Deux campagnes malveillantes sur npm ont émergé à trois semaines d’intervalle. À lire les titres, elles se fondent en un seul message : les paquets npm sont dangereux. À lire les rapports, elles diffèrent exactement sur le point qui décide si un développeur a la moindre occasion de les arrêter.

Cas un : le ver qui a besoin de votre confiance

Un ver voleur d’identifiants est apparu d’abord dans keyv@6.0.0 et s’est répandu au-delà des espaces de noms Keyv et Cacheable, jusqu’à des centaines de paquets, le 4 août 2026.

La version malveillante a ajouté node setup.mjs comme commande preinstall en laissant intact le code compilé de la bibliothèque. La première étape vérifie la présence de l’environnement Bun, le télécharge si nécessaire et passe la main à un bundle compilé de 727 680 octets. Selon l’analyse de SafeDep, ce bundle récolte du matériau GitHub, npm, cloud, Vault, Kubernetes, base de données et clés privées, lit la mémoire du runner GitHub Actions et embarque sa propre mécanique de publication npm, ce qui lui permet de se répandre.

Le dépôt conservait en plus des hooks distincts pour Claude Code et Visual Studio Code. Ils comptent, et la réserve que le rapport y attache compte tout autant : ils « peuvent exécuter la charge dès qu’un utilisateur accorde sa confiance à l’espace de travail ou autorise la configuration du projet ».

Il y a une porte. Quelqu’un doit la franchir.

Cas deux : celui qui ne demande rien

Le 21 août, TrendAI a signalé quatorze paquets npm trojanisés se faisant passer pour des utilitaires de calendrier et de séries. Ils fonctionnent : la fonctionnalité promise est là, et c’est ce qui les maintient installés.

Dessous, le fichier d’entrée sert de chargeur pour une porte dérobée Linux déguisée en accélérateur mathématique natif. Le nom du fichier change d’un paquet à l’autre (math-core.bin, calc-math.dat, calc-cache.bin et d’autres), mais le contenu est la même balise.

C’est au niveau du mécanisme que ce cas s’éloigne du premier. Dans les mots des chercheurs : « Quand le module se charge, il localise le binaire embarqué, le marque exécutable et le lance comme processus d’arrière-plan détaché. Aucun appel à une fonction de hook d’installation n’est nécessaire ; un seul import n’importe où dans le graphe de dépendances, même transitif, suffit à exécuter la charge. »

Aucun hook d’installation. Aucune demande de confiance. Aucune fonction exportée que quelqu’un doive appeler. Un import trois niveaux plus bas, dans une dépendance que vous n’avez jamais choisie, suffit.

Pourquoi la différence est l’information

Les deux sont des attaques contre la chaîne d’approvisionnement npm. Les réunir dans un seul avertissement fait perdre la seule partie qui change ce que l’on fait.

Le cas un est ralenti par une décision humaine. npm 12 bloque par défaut les scripts de cycle de vie des dépendances non approuvées, et les hooks de l’éditeur ont besoin que quelqu’un accorde sa confiance à l’espace de travail. Les clients npm anciens et les autres chemins d’installation qui autorisent ces scripts restent exposés : la protection est réelle et conditionnelle à la fois.

Le cas deux n’a pas cette étape. La charge s’exécute à l’import, ce qui veut dire que les défenses qui comptent sont celles qui ne dépendent pas de l’attention de quiconque : versions de dépendances figées, discipline du lockfile, et savoir ce qu’il y a réellement dans votre arbre.

Quiconque repart d’ici avec « il faut se méfier des paquets npm » a sauté la moitié qui indique où placer l’effort.

Les chiffres d’ampleur ne concordent pas, et le rapport le dit

C’est là que l’histoire se cite mal, alors voici le tableau complet.

SafeDep a vérifié 353 versions empoisonnées sur 79 noms de paquets. Sa propre surveillance situait l’empreinte plus large à 442 versions sur 353 noms. Aikido a ensuite signalé au moins 868 paquets sur 1 381 versions.

Trois décomptes, trois sources, et le rapport est explicite : « aucun des deux totaux plus larges n’était reproductible de façon indépendante à partir d’une liste publique complète à la date de clôture ».

Il ajoute une seconde réserve qui pèse plus lourd que l’écart : ces totaux « comptent des artefacts de paquets malveillants, pas des systèmes victimes. Ils établissent l’ampleur de la campagne mais ne montrent pas combien de machines ont installé ou exécuté la charge ».

Si un chiffre unique et assuré vous est présenté sur cette campagne, il a donc été choisi parmi trois qui se contredisent, et il compte des paquets plutôt que des infections dans tous les cas.

L’étape de remédiation qui va contre l’instinct

C’est la phrase la plus utile des deux rapports, et elle passe facilement inaperçue.

La charge installe un veilleur de révocation d’identifiants. SafeDep conseille à ceux qui traitent l’incident de retirer ce veilleur avant de renouveler les jetons et les clés exposés, car c’est la révocation qui le déclenche : renouveler d’abord peut exécuter un gestionnaire local déposé par l’attaquant.

La réaction instinctive à un vol d’identifiants est de tout renouveler immédiatement. Ici, cet instinct fait partir le piège.

L’appréciation de Socket sur les personnes concernées est large : « tout poste de travail ou runner ayant exécuté une version affectée doit être considéré comme exposé du point de vue des identifiants ».

Pourquoi une liste de paquets ne vous sauvera pas

Le rapport note que le registre changeait trop vite pour soutenir une liste fixe à l’échelle de la campagne. Quelques heures après les premiers constats, des versions antérieures avaient été rétablies comme latest pour au moins neuf paquets de l’ensemble initial de SafeDep.

La conséquence pratique : les vérifications d’exposition doivent utiliser des noms de paquets exacts, des versions résolues et des lockfiles, pas une liste mise en cache des étiquettes courantes. Une liste de blocage au niveau de l’espace de noms risque à la fois de manquer des versions empoisonnées et de signaler des versions qui ne l’ont jamais été.

La forme est familière. Une liste qui a l’air faisant autorité, qui est périmée au moment où on la lit, et qui produit des réponses assurées dans les deux sens.

Ce qu’il faut en retenir

Cherchez à savoir si vos chemins d’installation exécutent des scripts de cycle de vie. Si vous êtes sur une version de npm qui les bloque par défaut, le cas un a une porte devant lui. Sinon, il n’en a pas.

Sachez jusqu’où peut aller un import transitif. Le cas deux n’a besoin que d’un module chargé quelque part dans le graphe, ce qui fait de la profondeur des dépendances une propriété de sécurité et non une question de rangement.

Et si vous traitez un jour un incident de vol d’identifiants, lisez l’ordre des remédiations avant de renouveler. Cette fois, le premier geste évident était précisément celui qui déclenche la charge.

Sources

Newcomer AI-Visibility Tracker · known from