npm : --ignore-scripts ne suffit plus, la charge s'exécute à l'import
La compromission des paquets @asyncapi exécute la charge à l'import du module, pas à l'installation. Pourquoi --ignore-scripts échoue et comment détecter par YARA.
Depuis des années, le conseil standard pour se protéger des paquets npm malveillants tient en une option : npm install --ignore-scripts. Elle désactive l'exécution des scripts de cycle de vie, notamment postinstall, par lequel transite l'immense majorité des charges de compromission de la chaîne d'approvisionnement. npm 12 va même plus loin en bloquant ces scripts par défaut. Le 14 juillet 2026, Microsoft Threat Intelligence a documenté une attaque qui rend ce conseil caduc : la compromission de l'organisation @asyncapi, où la charge ne s'exécute pas à l'installation, mais au chargement du module.
C'est un changement de paradigme qu'il faut intégrer. --ignore-scripts ne bloque que les hooks d'installation. Si le code malveillant se déclenche quand un build, un job d'intégration continue ou une application importe le module pour la première fois, aucune de ces protections n'entre en jeu. La charge se réveille au require ou à l'import, en plein cœur de l'exécution légitime.
Ce qui a été compromis
Microsoft rapporte que cinq versions de paquets, réparties sur quatre noms, ont été republiées en environ quatre-vingt-dix minutes, chacune portant le même chargeur injecté. Les paquets concernés sont @asyncapi/specs (dans la préversion 6.11.2-alpha.1 et la version stable 6.11.2), @asyncapi/generator@3.3.1, @asyncapi/generator-components@0.7.1 et @asyncapi/generator-helpers@1.1.1. Ensemble, ces paquets totalisent plus de deux millions de téléchargements hebdomadaires, ce qui donne la mesure de la surface exposée.
L'attaque a exploité les pipelines de publication de confiance dans GitHub Actions, permettant au code malveillant de passer sans reposer sur les hooks d'installation npm traditionnels. C'est la technique T1195.002 (Supply Chain Compromise: Compromise Software Supply Chain). La charge, apparentée au cadriciel Miasma déjà observé lors des attaques Shai-Hulud, combine le vol d'identifiants, l'empoisonnement d'outils d'assistance, la propagation de type ver et un canal de commande et contrôle multi-protocoles utilisant HTTP, Nostr, IPFS, BitTorrent, libp2p et Ethereum.
Pourquoi l'exécution à l'import change la détection
Une charge postinstall s'exécute une fois, au moment de l'installation, dans un contexte relativement identifiable. Une charge à l'import s'exécute chaque fois que le module est chargé, dans le processus applicatif lui-même. Cela déplace le point de détection : il ne s'agit plus de surveiller npm install, mais de repérer le comportement anormal d'un processus Node.js en cours d'exécution, et de disposer de signatures sur les artefacts déposés.
La charge écrit un fichier sync.js sous %LOCALAPPDATA%\NodeJS\ pour établir sa persistance, ce qui relève de T1547, et procède à la collecte massive d'identifiants (T1555). Ces artefacts fichier sont un point d'ancrage solide pour une règle YARA, qui reste valable même si le vecteur d'injection évolue.
Une règle YARA sur les artefacts et les marqueurs C2
La règle suivante cible les chaînes caractéristiques du chargeur : le chemin de persistance, et les marqueurs de canaux de commande et contrôle atypiques pour un paquet npm légitime. Un paquet de génération de code n'a aucune raison de référencer IPFS, Nostr ou une adresse Ethereum.
rule Npm_Asyncapi_ImportTime_Loader
{
meta:
description = "Detecte le chargeur injecte dans les paquets @asyncapi compromis (juillet 2026)"
reference = "https://www.microsoft.com/en-us/security/blog/2026/07/15/unpacking-asyncapi-npm-supply-chain-compromise-import-time-payload-delivery/"
author = "ThreatClaw"
date = "2026-07-19"
strings:
$persist = "\\NodeJS\\sync.js" ascii wide nocase
$ipfs = "ipfs" ascii nocase
$nostr = "nostr" ascii nocase
$eth = "ethereum" ascii nocase
$b64eval = "Buffer.from" ascii
$childproc = "child_process" ascii
condition:
$persist or
( 2 of ($ipfs, $nostr, $eth) and $b64eval and $childproc )
}Cette règle se déclenche soit sur le chemin de persistance connu, soit sur la combinaison improbable, dans un module npm, de plusieurs protocoles de commande et contrôle exotiques avec de l'exécution dynamique de code et le lancement de processus enfants. Le second bras vise à capter des variantes qui changeraient le nom du fichier de persistance mais conserveraient le canal C2.
Compléter avec une détection à la construction
Côté prévention, un scanner de type Nuclei ou une inspection statique du répertoire node_modules avant le build permet de repérer les versions compromises précises. Épinglez vos dépendances par version exacte et par empreinte d'intégrité, et bloquez les versions listées ci-dessus dans votre gestionnaire de dépendances. Surveillez également les connexions sortantes inattendues d'un runner d'intégration continue vers des adresses IPFS ou des relais Nostr, qui n'ont rien à faire dans un pipeline de build de générateur de documentation.
La leçon opérationnelle est claire : le modèle mental « les scripts d'installation sont le seul risque » est dépassé. Une charge peut sommeiller dans le corps même d'un module et se réveiller à l'import, dans le processus le plus légitime qui soit. Détecter ces menaces demande des signatures maintenues sur les artefacts réels, pas seulement des règles sur le cycle de vie npm.
C'est la vocation du feed YARA ThreatClaw : des règles de détection construites à partir d'échantillons réels, testées contre un corpus de code légitime pour limiter les faux positifs, et actualisées au rythme des compromissions de la chaîne d'approvisionnement.
Articles liés
IronWorm cache un binaire Rust déclenché au preinstall, moissonne les clés cloud et IA, puis se propage via GitHub. La règle YARA pour le détecter.
Un feed de règles ne vaut pas par son nombre de règles, mais par la preuve qu'elles fonctionnent et par ce que vous en faites quand elles se déclenchent. Testées sur moteur réel, anti-faux-positifs prouvé, signées, et chaque règle porte un playbook d'investigation relié à nos autres moteurs.
De juin à août 2026, ThreatClaw a forgé 72 nouvelles familles de malware dans son feed YARA : Prometei, WannaCry, EternalBlue, GhostNFC, SpyNote, Mamont, Neshta… Chacune validée sur 5 694 binaires légitimes, zéro faux positif.
Botnet Prometei sur Linux, injection de code Windows, macros Office, Android, téléchargeurs. ThreatClaw ajoute 14 familles de malware fraîches à son feed YARA, 391 règles, validées sur 5 694 binaires légitimes sans un seul faux positif.