🔍 Contexte

Le 11 mai 2026, TanStack a publié un post-mortem détaillé d’une compromission de chaîne d’approvisionnement npm survenue entre 19:20 et 19:26 UTC. L’incident a affecté 42 packages @tanstack/* avec 84 versions malveillantes publiées via un enchaînement de trois vulnérabilités dans le pipeline GitHub Actions.

⚙️ Vecteur d’attaque — Trois vulnérabilités chaînées

1. Pattern « Pwn Request » via pull_request_target Le workflow bundle-size.yml utilisait le déclencheur pull_request_target et effectuait un checkout du code de la PR fork, permettant l’exécution de code non approuvé dans le contexte du dépôt de base.

2. Empoisonnement du cache GitHub Actions Le payload malveillant vite_setup.mjs (~30 000 lignes) a écrit dans le répertoire pnpm-store sous la clé exacte que release.yml utiliserait lors du prochain push sur main (Linux-pnpm-store-6f9233a50def742c09fde54f56553d6b449a535adf87d4083690539f49ae4da11). Le cache empoisonné (1,1 Go) a persisté après fermeture de la PR.

3. Extraction mémoire du token OIDC Lors de l’exécution de release.yml sur main, les binaires malveillants restaurés depuis le cache ont localisé le processus GitHub Actions Runner.Worker via /proc/*/cmdline, lu /proc/<pid>/maps et /proc/<pid>/mem pour extraire le token OIDC en mémoire, puis l’ont utilisé pour publier directement sur registry.npmjs.org — contournant entièrement l’étape Publish Packages du workflow légitime.

🦠 Comportement du malware

Le script router_init.js (~2,3 Mo, obfusqué), exécuté lors du npm install / pnpm install / yarn install, effectuait les actions suivantes :

  • Collecte de credentials : AWS IMDS/Secrets Manager, GCP metadata, tokens Kubernetes, Vault, ~/.npmrc, tokens GitHub, clés SSH privées
  • Exfiltration via le réseau Session/Oxen (filev2.getsession.org, seed{1,2,3}.getsession.org) — chiffré de bout en bout
  • Auto-propagation : énumération des packages maintenus par la victime via l’API npm et republication avec la même injection

📅 Chronologie clé

  • 2026-05-10 17:16 : Création du fork github.com/zblgg/configuration (renommé pour éviter les recherches)
  • 2026-05-10 23:29 : Commit malveillant 65bf499d avec identité forgée claude <claude@users.noreply.github.com>
  • 2026-05-11 11:11 : Exécution de vite_setup.mjs via le job benchmark-pr
  • 2026-05-11 11:29 : Cache empoisonné sauvegardé
  • 2026-05-11 19:20–19:26 : Publication des 84 versions malveillantes via deux runs de release.yml
  • 2026-05-11 ~19:50 : Détection externe par le chercheur ashishkurmi (StepSecurity) ~20 minutes après la publication

🎯 Impact

  • 42 packages @tanstack/* affectés (familles @tanstack/router, @tanstack/history, @tanstack/start-*, etc.)
  • Familles confirmées non affectées : @tanstack/query*, @tanstack/table*, @tanstack/form*, @tanstack/virtual*, @tanstack/store, @tanstack/start
  • Aucun token npm volé ; le workflow de publication légitime n’a pas été compromis directement
  • Toute machine ayant installé une version affectée le 2026-05-11 doit être considérée comme potentiellement compromise

📄 Type d’article

Post-mortem technique publié par l’équipe TanStack, visant à documenter précisément le vecteur d’attaque, la chronologie, les IOCs et les leçons tirées pour la communauté open source et les équipes de sécurité.

🧠 TTPs et IOCs détectés

Acteurs de menace

  • zblgg (unknown) —
  • voicproducoes (unknown) —

TTP

  • T1195.001 — Supply Chain Compromise: Compromise Software Dependencies and Development Tools (Initial Access)
  • T1059.007 — Command and Scripting Interpreter: JavaScript (Execution)
  • T1552.001 — Unsecured Credentials: Credentials In Files (Credential Access)
  • T1552.005 — Unsecured Credentials: Cloud Instance Metadata API (Credential Access)
  • T1003 — OS Credential Dumping (Credential Access)
  • T1567 — Exfiltration Over Web Service (Exfiltration)
  • T1036.005 — Masquerading: Match Legitimate Name or Location (Defense Evasion)
  • T1072 — Software Deployment Tools (Execution)
  • T1176 — Browser Extensions (Persistence)
  • T1608.001 — Stage Capabilities: Upload Malware (Resource Development)

IOC

Malware / Outils

  • router_init.js (stealer)
  • vite_setup.mjs (loader)

🟡 Indice de vérification factuelle : 63/100 (moyenne)

  • ⬜ tanstack.com — source non référencée (0pts)
  • ✅ 17413 chars — texte complet (fulltext extrait) (15pts)
  • ✅ 10 IOCs (IPs/domaines/CVEs) (10pts)
  • ✅ 1/5 IOC(s) confirmé(s) (ThreatFox, URLhaus, VirusTotal) (8pts)
  • ✅ 10 TTPs MITRE identifiées (15pts)
  • ✅ date extraite du HTML source (10pts)
  • ✅ acteur(s) identifié(s) : zblgg, voicproducoes (5pts)
  • ⬜ pas de CVE à vérifier (0pts)

IOCs confirmés externellement :

  • filev2.getsession.org (domain) → VT (17/92 détections) + ThreatFox (Unknown malware)

🔗 Source originale : https://tanstack.com/blog/npm-supply-chain-compromise-postmortem