En octobre 2026, la menace la plus sérieuse pour un projet Node.js n'était pas dans Node.js. La faille du décodeur Brotli se corrige par une mise à jour. Les attaques de la chaîne d'approvisionnement logicielle (supply chain), elles, entrent par les portes qu'on ouvre soi-même chaque jour : npm install, un binaire téléchargé, un workflow de CI.
En trois semaines : un SDK npm transformé en ver, un paquet piégé au moment même de sa publication, des centaines de dépôts GitHub dotés d'un faux workflow « d'audit de sécurité », et les binaires de la CLI d'OVHcloud remplacés pendant 94 minutes. Voici ce qui s'est passé, ce que ces attaques ont en commun et les réglages qui protègent un projet Node.js.
Ce qui s'est passé en octobre
- @subql/common 5.8.3 (5 octobre). Le processus de publication du paquet a été modifié pour remplacer, juste avant l'envoi, le paquet construit par une archive téléchargée sur
ci-artifacts.dev. Le paquet est parti par la voie officielle de publication de confiance. La charge vole les secrets (.npmrc,.env, identifiants AWS, clés SSH, kubeconfig) et s'exécute à l'installation et à l'import. La version saine est la 5.8.2. - tensorlake 0.5.144 (8 octobre). Des fichiers malveillants ont été poussés sur la branche principale du dépôt sous le nom d'un mainteneur, puis publiés par le processus normal, avec une attestation de provenance valide. Un script
preinstalltélécharge le moteur Bun et lance un ver de la famille Shai-Hulud. Socket l'a repéré onze minutes après sa publication. - GhostAction (à partir du 7 octobre). Avec des jetons GitHub personnels volés, des attaquants ont ajouté à des dépôts des workflows nommés
security-audit.ymlougithub_actions_security.yml, qui envoient les secrets de la CI vers l'extérieur. - CLI OVHcloud (19 octobre). Avec le compte GitHub d'un contributeur, un attaquant a remplacé les binaires des versions 0.11.0 à 0.15.0, ainsi que le fichier
checksums.txt, de 14 h 47 à 16 h 21 (heure de Paris). Le binaire piégé vole les secrets présents sur le disque. La version 0.16.0 est saine ; les installations pargo installou par compilation, et l'image Docker, n'ont pas été touchées.
Le même mois, la bibliothèque Python LiteLLM a connu un scénario voisin sur PyPI : l'écosystème JavaScript n'a pas l'exclusivité.
Ce que fait le ver de tensorlake
tensorlake mérite qu'on s'y arrête, parce qu'il résume la menace actuelle. Selon les analyses de Socket et de StepSecurity, une fois lancé, il :
- vole les jetons npm et GitHub, les identifiants AWS (y compris via le service de métadonnées), les secrets Vault et Kubernetes, les clés SSH, les fichiers
.env, des portefeuilles de cryptomonnaies et les configurations des assistants de code (Claude Code, Cursor, Windsurf et d'autres) ; - se propage : il liste les paquets que la victime a le droit de publier et en publie des versions infectées, avec une provenance Sigstore en règle ;
- s'installe durablement : il écrit des fichiers
.claude/settings.jsonet.vscode/tasks.jsondans les dépôts qu'il atteint, pour se relancer à l'ouverture du projet dans Claude Code ou VS Code, et dépose un service nommégh-token-monitor; - se venge : ce service surveille le jeton GitHub volé. S'il est révoqué, il exécute une commande fournie par l'attaquant ; le code contient d'ailleurs la chaîne
IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner.
Ce dernier point change l'ordre des opérations. Sur une machine infectée, on retire d'abord le service, on révoque les jetons ensuite. L'inverse peut coûter le contenu du poste.
Pourquoi les protections habituelles n'ont pas suffi
Ces attaques ont un point commun : elles passent à travers des protections qu'on croyait suffisantes.
- La provenance prouve d'où vient un paquet, pas qu'il est sain. tensorlake a été construit par le bon dépôt, avec le bon processus : l'attestation disait vrai. C'est le dépôt lui-même qui était compromis.
- Une somme de contrôle publiée à côté du fichier ne protège pas d'un attaquant qui contrôle les deux. Pour la CLI OVHcloud,
checksums.txta été remplacé avec les binaires. C'est un client qui a donné l'alerte, parce que sa CI comparait le fichier téléchargé à une empreinte qu'il avait enregistrée lui-même. - Bloquer les scripts d'installation ne suffit plus. C'est efficace contre tensorlake, qui passe par
preinstall. Pas contre @subql/common, qui s'exécute aussi à l'import, c'est-à-dire au premier lancement de l'application ou des tests.
Vérifier ses projets
J'ai fait ces vérifications sur mes propres dépôts avant d'écrire cet article : 64 fichiers de verrouillage (pnpm, npm, yarn), aucune des versions citées, aucun workflow GhostAction, aucun service gh-token-monitor. Les commandes, à lancer à la racine de votre dossier de projets :
# Paquets concernés dans les fichiers de verrouillage
grep -rlE 'tensorlake|@subql/common' --exclude-dir=node_modules \
--include=package-lock.json --include=pnpm-lock.yaml \
--include=yarn.lock --include=bun.lock .
# Dans un projet précis : qui tire ce paquet, et en quelle version
npm ls tensorlake @subql/common
pnpm why tensorlake
# Workflows ajoutés par GhostAction
find . -path '*/.github/workflows/*' -not -path '*/node_modules/*' \
\( -name 'security-audit.yml' -o -name 'github_actions_security.yml' \)
# Fichiers de configuration d'éditeur modifiés depuis le début du mois
git log --since=2026-10-01 --stat -- .claude/settings.json .vscode/tasks.jsonPuis, sur chaque poste de développement et chaque runner de CI auto-hébergé, la persistance du ver :
# Linux
systemctl --user status gh-token-monitor.service
ls ~/.config/gh-token-monitor/
# macOS
ls ~/Library/LaunchAgents/com.user.gh-token-monitor.plist
# Windows (PowerShell) : tâche planifiée qui lance monitor.ps1
Get-ScheduledTask | Where-Object { $_.Actions.Arguments -match 'monitor.ps1' }Pour la CLI OVHcloud : si vous l'avez installée ou mise à jour le 19 octobre entre 14 h 47 et 16 h 21 par le script d'installation, par téléchargement manuel ou par sa commande de mise à jour intégrée, supprimez le binaire, installez la 0.16.0 et changez les secrets présents sur la machine, à commencer par les identifiants de l'API OVHcloud.
Si une trace apparaît, la machine est compromise. Isolez-la, retirez la persistance, puis changez tous les secrets qu'elle a pu lire (jetons npm et GitHub, clés cloud, clés SSH, variables d'environnement) et reconstruisez-la depuis une source sûre. Retirer la dépendance ne retire pas ce qu'elle a installé.
Les réglages qui protègent un projet Node.js
Aucun réglage n'arrête tout. Ensemble, ils transforment une compromission probable en une alerte sans conséquence.
- Attendre avant d'installer une version neuve. C'est la mesure la plus rentable de 2026 : les paquets piégés sont repérés en quelques minutes ou quelques heures, rarement plus de quelques jours. Avec pnpm,
minimumReleaseAge: 4320danspnpm-workspace.yamlrefuse toute version publiée depuis moins de trois jours (la valeur est en minutes). npm dispose désormais d'un réglage comparable, désactivé par défaut. - Ne pas exécuter les scripts d'installation des dépendances. pnpm ne les exécute plus depuis sa version 10, sauf pour les paquets explicitement autorisés (
onlyBuiltDependencies). npm 12, sorti en juillet 2026, fait de même par défaut, avec une liste d'autorisation gérée parnpm approve-scripts. Sur une version plus ancienne,npm ci --ignore-scriptsen CI. - Installer ce qui est verrouillé, et rien d'autre. En CI et en production :
npm cioupnpm install --frozen-lockfile, jamais unnpm installqui résout à nouveau les versions. Et relire le diff du fichier de verrouillage en revue de code : une dépendance qui apparaît sans raison doit se voir. - Épingler les actions GitHub par empreinte.
uses: actions/checkout@<sha>plutôt que@v4: une étiquette se déplace, une empreinte non. - Réduire ce qu'un vol rapporte. Pas de jeton npm de longue durée dans la CI : la publication de confiance (OIDC) le remplace. Des jetons GitHub à portée fine et à durée limitée. Des secrets de CI réservés aux workflows qui en ont besoin, et des environnements protégés pour la production. La faille GitLab CVSS 10 rappelait déjà ce que vaut un serveur de CI pour un attaquant.
- Vérifier les binaires avec une source indépendante. Une empreinte enregistrée lors de la première installation, comme ce client d'OVHcloud, ou une attestation signée vérifiée avec
gh attestation verify, plutôt qu'un fichier de sommes de contrôle téléchargé au même endroit que le binaire. - Traiter les fichiers de configuration d'éditeur comme du code.
.vscode/tasks.jsonet.claude/settings.jsonpeuvent lancer des commandes : ils passent en revue de code comme le reste. Dans VS Code, le mode restreint (Workspace Trust) empêche les tâches d'un dossier non approuvé de s'exécuter. - Côté mainteneur. Double authentification sur npm et sur GitHub, branche principale protégée, publications immuables : c'est l'option qu'OVHcloud a activée après l'incident.
Ce que j'en retiens
- Octobre 2026 a vu des paquets npm piégés à la publication avec une provenance valide, et des binaires remplacés en même temps que leurs sommes de contrôle.
- À vérifier : vos fichiers de verrouillage (tensorlake 0.5.144, @subql/common 5.8.3), vos workflows (GhostAction), vos postes et runners (
gh-token-monitor), et la CLI OVHcloud si vous l'avez installée le 19 octobre. - Sur une machine infectée par tensorlake, on retire le service de surveillance avant de révoquer les jetons.
- Un délai de quelques jours avant d'adopter une nouvelle version, l'absence de scripts d'installation et une installation strictement verrouillée arrêtent la plupart de ces attaques.
- Les fichiers de configuration d'éditeur et de CI sont du code exécutable : ils se relisent comme tel.
Vous maintenez une application Node.js et vous ne savez pas exactement ce que votre CI installe, ni ce qu'un jeton volé permettrait ? Je peux auditer vos dépendances et votre chaîne de publication, mettre en place ces réglages sans casser vos builds et vous aider à réagir si une trace apparaît. Décrivez-moi votre projet, je vous réponds rapidement.
Sources : analyse de Socket sur tensorlake 0.5.144 (8 octobre 2026), StepSecurity et Endor Labs ; IT-Connect sur la compromission de la CLI OVHcloud (19 octobre 2026) ; suivi des incidents d'octobre 2026 publié par AgentBeam ; documentation de pnpm et de npm. Article à jour au 29 octobre 2026.