1 points par GN⁺ 2 시간 전 | 1 commentaires | Partager sur WhatsApp
  • Entre 19:20 et 19:26 UTC le 2026-05-11, l’attaquant a publié 84 versions malveillantes sur 42 paquets npm @tanstack/
  • La chaîne d’attaque combine le « Pwn Request » de pull_request_target, l’empoisonnement du cache GitHub Actions et l’extraction d’un jeton OIDC depuis la mémoire du runner
  • Le jeton npm et le workflow de publication n’ont pas été volés ni compromis ; le malware a envoyé directement un POST au registre avec les droits OIDC trusted publisher
  • L’installation d’une version affectée a pu exposer des identifiants AWS, GCP, Kubernetes, Vault, GitHub, npm et SSH, qui doivent être remplacés
  • Toutes les versions affectées ont été marquées comme obsolètes, la suppression des tarballs a été lancée avec npm security, et l’issue de suivi ainsi que le GitHub Security Advisory ont été publiés

Vue d’ensemble de l’incident

  • Entre 19:20 et 19:26 UTC le 2026-05-11, l’attaquant a publié 84 versions malveillantes sur 42 paquets npm @tanstack/*
  • La chaîne d’attaque combine le modèle « Pwn Request » de pull_request_target, l’empoisonnement du cache GitHub Actions au-delà de la frontière de confiance fork↔base, et l’extraction d’un jeton OIDC depuis la mémoire du processus runner de GitHub Actions
  • Il a été confirmé que les jetons npm n’ont pas été volés et que le workflow npm publish lui-même n’a pas été compromis
  • Les versions malveillantes ont été détectées publiquement en moins de 20 minutes par le chercheur externe ashishkurmi de stepsecurity
  • Toutes les versions affectées ont été marquées comme obsolètes, et la suppression des tarballs du registre a été engagée avec npm security
  • Les utilisateurs ayant installé une version affectée le 2026-05-11 doivent remplacer les identifiants AWS, GCP, Kubernetes, Vault, GitHub, npm et SSH accessibles depuis l’hôte d’installation
  • L’issue de suivi est TanStack/router#7383, et le GitHub Security Advisory est GHSA-g7cv-rxg3-hmpx

Périmètre d’impact

  • Paquets affectés

    • Le périmètre couvre 42 paquets et 84 versions, avec 2 versions publiées par paquet à environ 6 minutes d’intervalle
    • La liste complète figure dans l’issue de suivi
    • Les gammes de produits confirmées comme non affectées sont @tanstack/query*, @tanstack/table*, @tanstack/form*, @tanstack/virtual*, @tanstack/store et le méta-paquet @tanstack/start
    • @tanstack/start-* ne figure pas dans la liste confirmée des éléments non affectés
  • Fonctionnement du malware

    • Lorsqu’un environnement développeur ou CI exécute npm install, pnpm install ou yarn install sur une version affectée, npm résout une entrée malveillante dans optionalDependencies et récupère un commit de payload orphelin depuis le réseau du fork
    • Le script de cycle de vie prepare s’exécute ensuite, et un router_init.js obfusqué d’environ 2,3 Mo, dissimulé dans le tarball affecté, entre en action
    • Le script malveillant collecte des identifiants depuis des emplacements courants, notamment AWS IMDS/Secrets Manager, les métadonnées GCP, le jeton de service account Kubernetes, le jeton Vault, ~/.npmrc, le jeton GitHub, la CLI gh, .git-credentials et la clé privée SSH
    • Les données exfiltrées transitent via le réseau de téléversement de fichiers du messager Session/Oxen, avec pour destinations filev2.getsession.org et seed{1,2,3}.getsession.org
    • Ce réseau étant chiffré de bout en bout et sans C2 contrôlé par l’attaquant, les mesures de mitigation réseau se limitent au blocage d’IP/domaines
    • La logique d’auto-propagation énumère ensuite d’autres paquets maintenus par la victime via registry.npmjs.org/-/v1/search?text=maintainer:<user>, puis les republie avec la même méthode d’injection
    • Comme le payload s’exécute dans le cadre du cycle de vie de npm install, tout hôte ayant installé une version affectée le 2026-05-11 doit être considéré comme potentiellement compromis

Chronologie

  • Avant l’attaque : étape d’empoisonnement du cache

    • Le 2026-05-10 à 17:16 UTC, l’attaquant a créé github.com/zblgg/configuration, un fork de TanStack/router, puis en a changé le nom pour éviter d’apparaître dans la recherche de forks
    • Le 2026-05-10 à 23:29 UTC, le commit malveillant 65bf499d16a5e8d25ba95d69ec9790a6dd4a1f14 a été créé dans ce fork avec l’identité falsifiée claude <claude@users.noreply.github.com>
    • Ce commit ajoutait packages/history/vite_setup.mjs, une charge utile JS bundle d’environ 30 000 lignes, et incluait [skip ci] dans le message de commit pour empêcher la CI de se déclencher sur l’événement push
    • Vers 10:49 UTC le 2026-05-11, zblgg a ouvert la PR #7378 vers le main de TanStack/router avec le titre « WIP: simplify history build »
    • bundle-size.yml et labeler.yml se lançaient tous deux automatiquement sur les PR via pull_request_target, et pull_request_target contournait le garde d’approbation pour les premiers contributeurs, donc aucune approbation supplémentaire n’était nécessaire
    • pr.yml, qui utilisait pull_request, est resté bloqué en attente d’approbation et ne s’est pas exécuté
    • Entre 11:01 et 11:11 UTC le 2026-05-11, zblgg a effectué plusieurs force-push sur la tête de la PR, déclenchant des exécutions pull_request_target supplémentaires
    • Le 2026-05-11 à 11:11 UTC, le commit malveillant 65bf499d a été placé en tête de la PR, puis le job benchmark-pr de bundle-size.yml a checkout refs/pull/7378/merge avant d’exécuter pnpm install et pnpm nx run @benchmarks/bundle-size:build, ce qui a déclenché vite_setup.mjs
    • Le 2026-05-11 à 11:29 UTC, un cache GitHub Actions de 1,1 Go nommé Linux-pnpm-store-6f9233a50def742c09fde54f56553d6b449a535adf87d4083690539f49ae4da11 a été enregistré dans TanStack/router
    • Ce cache a été enregistré dans le scope refs/heads/main et configuré pour correspondre à la clé que release.yml récupérerait lors du push suivant sur main
    • Le 2026-05-11 à 11:31 UTC, l’attaquant a remis la PR sur b1c061af, le HEAD de main à ce moment-là, afin que la PR visible ressemble à un no-op sans fichier modifié ; dans la même minute, la PR a été fermée et la branche supprimée, mais le cache empoisonné est resté
  • Déclenchement : étape de publication

    • Le 2026-05-11 à 19:15 UTC, Manuel a fusionné la PR #7369, provoquant un push sur main, puis l’exécution du workflow release.yml 25613093674 a démarré à 19:15:44 avant d’échouer
    • Le 2026-05-11 à 19:20:39 UTC, le registre npm a reçu la publication de @tanstack/history@1.161.9 et de 41 packages siblings
    • Au total, environ 84 versions réparties sur 42 packages ont été publiées, mais à cette seconde précise seule environ la moitié est visible, le reste ayant été publié lors d’une seconde exécution
    • L’authentification de publication s’est faite via une liaison trusted-publisher OIDC pour TanStack/router release.yml@refs/heads/main, mais elle n’est pas intervenue lors de l’étape Publish Packages du workflow, sautée à cause de l’échec des tests
    • Le véritable éditeur était le malware exécuté pendant les étapes de test/nettoyage, qui a mint un token OIDC avec l’autorisation id-token: write puis a effectué un POST direct vers registry.npmjs.org
    • Le 2026-05-11 à 19:20:47 UTC, l’exécution 25613093674 s’est terminée avec le statut failure
    • Le 2026-05-11 à 19:16 UTC, Manuel a fusionné la PR #7382, provoquant un second push sur main, et l’exécution du workflow 25691781302 a démarré à 19:16:22
    • Cette seconde exécution a elle aussi restauré le même cache empoisonné, et le 2026-05-11 à 19:26:14 UTC un second ensemble de versions par package, dont @tanstack/history@1.161.12, a été publié via le même mécanisme OIDC
    • Le 2026-05-11 à 19:26:20 UTC, l’exécution 25691781302 s’est elle aussi terminée avec le statut failure
  • Détection et réponse

    • Vers 19:50 UTC le 2026-05-11, le chercheur externe carlini a ouvert l’issue #7383 avec l’empreinte malveillante optionalDependencies et la liste des packages
    • La liste initiale ne couvrait que 14 packages sur 42, et le chercheur a également alerté directement la sécurité de npm
    • Vers 20:00 UTC le 2026-05-11, Manuel a confirmé l’incident dans #7383 et a commencé la réponse
    • Vers 20:10 UTC le 2026-05-11, Manuel a retiré les droits de push GitHub des autres membres de l’équipe par précaution face à un possible compromis des machines utilisateurs
    • Vers 20:30 UTC le 2026-05-11, Tanner a envoyé la liste complète des IOC et une demande de suppression côté registre des tarballs à security@npmjs.com, et a soumis un rapport formel de malware via npm
    • Vers 21:00 UTC le 2026-05-11, un scan complet des 295 packages @tanstack/* a confirmé un périmètre de 42 packages et 84 versions
    • Tanner a lancé la dépréciation npm des 84 packages affectés, et @tan_stack ainsi que les maintainers ont diffusé une alerte publique sur Twitter/X, LinkedIn et Bluesky
    • Le 2026-05-11 à 21:30 UTC, le vecteur d’empoisonnement du cache via pull_request_target dans bundle-size.yml et le fork zblgg/configuration ont été identifiés
    • Les entrées de cache de tous les dépôts GitHub TanStack/* ont été supprimées via l’API
    • Une PR de hardening a été fusionnée pour reconfigurer bundle-size.yml, ajouter un garde repository_owner et épingler les références des actions tierces à un SHA
    • L’avis officiel GitHub Security Advisory a été publié et un CVE a été demandé

Cause racine

  • Combinaison de trois vulnérabilités

    • L’attaque nécessitait les trois vulnérabilités ; aucune, prise isolément, n’était suffisante
    • Chaque vulnérabilité reliait les frontières de confiance des autres : le code d’une PR de fork passait dans le cache du dépôt de base, le cache du dépôt de base passait dans le runtime du workflow de release, et le runtime du workflow de release menait à des droits d’écriture sur le registre npm
  • Le modèle pull_request_target de type « Pwn Request »

    • bundle-size.yml s’exécutait en pull_request_target pour les PR de fork, puis, dans ce contexte de déclenchement, checkoutait la merge ref de la PR du fork avant d’exécuter le build
    • La structure essentielle était la suivante
    on:
      pull_request_target:
        paths: ['packages/**', 'benchmarks/**']
    
    jobs:
      benchmark-pr:
        steps:
          - uses: actions/checkout@v6.0.2
            with:
              ref: refs/pull/${{ github.event.pull_request.number }}/merge # fork's merged code
    
          - uses: TanStack/config/.github/setup@main # transitively calls actions/cache@v5
    
          - run: pnpm nx run @benchmarks/bundle-size:build # executes fork-controlled code
    
    • L’auteur du workflow avait séparé les jobs comment-pr et benchmark-pr pour cloisonner les frontières de confiance, et un commentaire YAML indiquait l’intention de garder benchmark-pr comme « untrusted with read-only permissions »
    • Cependant, la sauvegarde post-job de actions/cache@v5 n’est pas bloquée par permissions:, et l’écriture dans le cache utilise un token interne au runner, pas le GITHUB_TOKEN du workflow
    • Par conséquent, le réglage permissions: contents: read n’empêchait pas la mutation du cache
    • La portée du cache est au niveau du dépôt, et les exécutions pull_request_target utilisant la portée de cache du dépôt de base la partagent avec les push vers main
    • Une PR exécutée dans la portée de cache du dépôt de base peut donc polluer une entrée de cache qu’un workflow de production sur main restaurera plus tard
  • Empoisonnement du cache GitHub Actions

    • Le vite_setup.mjs malveillant était conçu pour écrire des données correspondant exactement à la clé de pnpm-store que le workflow release.yml légitime calculerait et rechercherait
    • La clé visée avait le format Linux-pnpm-store-${hashFiles('**/pnpm-lock.yaml')}
    • À la fin du job benchmark-pr, l’étape post-job de actions/cache@v5 enregistrait le pnpm store empoisonné précisément sous cette clé
    • Ensuite, lors de l’exécution de release.yml sur un push vers main, l’étape Setup Tools restaurait l’entrée empoisonnée comme prévu
    • Ce type d’attaque appartient à la famille des empoisonnements de cache GitHub Actions documentée par Adnan Khan en 2024 ; ce n’est pas un bug propre à TanStack, mais un problème de conception de GitHub Actions qui nécessite des mitigations volontaires
  • Extraction du token OIDC depuis la mémoire du runner

    • release.yml déclarait légitimement id-token: write, car c’était nécessaire pour la publication npm OIDC trusted publishing
    • Une fois le pnpm store empoisonné restauré sur le runner, un binaire contrôlé par l’attaquant se retrouvait sur le disque et était invoqué pendant l’étape de build
    • Ce binaire trouvait le processus GitHub Actions Runner.Worker via /proc/*/cmdline, puis lisait /proc/<pid>/maps et /proc/<pid>/mem pour dumper la mémoire du worker
    • Il extrayait ensuite depuis la mémoire le token OIDC émis à la volée par le runner dans le cadre du réglage id-token: write
    • Avec ce token extrait, il authentifiait directement des requêtes POST vers registry.npmjs.org, contournant entièrement l’étape Publish Packages du workflow
    • Cette méthode d’extraction mémoire est la même que celle utilisée lors de la compromission de tj-actions/changed-files en mars 2025, et le même script Python avec commentaire d’attribution a été utilisé
    • L’attaquant n’a pas inventé une nouvelle technique ; il a recombiné des travaux de recherche publics
  • Pourquoi chaque élément, pris seul, n’était pas suffisant

    • pull_request_target peut en soi être utilisé pour des tâches de confiance comme les labels ou les commentaires
    • L’empoisonnement de cache à lui seul, à l’intérieur d’une dépendance déjà compromise, nécessite encore un autre vecteur de publication
    • L’extraction d’un token OIDC, à elle seule, nécessite déjà une exécution de code préalable sur le runner

Détection et IOC

  • Voie de détection

    • La détection est venue de l’extérieur, pas de l’interne
    • carlini a ouvert l’issue #7383 environ 20 minutes après la publication, en fournissant une analyse technique complète
    • Tanner a reçu un appel de Socket.dev confirmant la situation juste après le lancement de la war room
  • Empreintes pour les mainteneurs downstream et les outils de sécurité

    • Dans les manifests des paquets @tanstack/*, l’IOC principal est l’entrée optionalDependencies suivante
    "optionalDependencies": {
      "@tanstack/setup": "github:tanstack/router#79ac49eedf774dd4b0cfa308722bc463cfe5885c"
    }
    
    • L’IOC de fichier est router_init.js à la racine du package ; il fait environ 2,3 Mo et n’est pas inclus dans "files"
    • La clé de cache est Linux-pnpm-store-6f9233a50def742c09fde54f56553d6b449a535adf87d4083690539f49ae4da11
    • Les URL des payloads de seconde étape sont https://litter.catbox.moe/h8nc9u.js, https://litter.catbox.moe/7rrc6l.mjs
    • Le réseau d’exfiltration est filev2.getsession.org, seed{1,2,3}.getsession.org
    • L’identité de commit falsifiée est claude <claude@users.noreply.github.com> ; il ne s’agit pas du véritable Anthropic Claude, mais d’un email GitHub no-reply forgé
    • Les véritables comptes des attaquants sont zblgg id 127806521, voicproducoes id 269549300
    • Le fork de l’attaquant est github.com/zblgg/configuration, renommé depuis un fork de TanStack/router pour éviter d’être retrouvé par recherche
    • Le commit orphan contenant le payload dans le réseau de forks est 79ac49eedf774dd4b0cfa308722bc463cfe5885c
    • Les workflow runs ayant exécuté la publication malveillante sont github.com/TanStack/router/actions/runs/25613093674 attempt 4 et github.com/TanStack/router/actions/runs/25691781302`

Leçons

  • Points positifs

    • Des chercheurs externes ont détecté l’incident et l’ont signalé avec tous les détails techniques environ 20 minutes après les faits
    • L’équipe de maintenance s’est immédiatement coordonnée sur plusieurs fuseaux horaires
    • La communauté de détection a établi en quelques heures des motifs IOC publics clairs
  • Points à améliorer

    • Il n’y avait pas d’alerting interne, et le fait de la compromission a été appris par un tiers
    • Un monitoring maison des publications est nécessaire, avec l’intention de collaborer plus étroitement avec des entreprises de recherche en sécurité de l’écosystème capables de détecter rapidement ce type de problème et de raccourcir la boucle de feedback
    • Le workflow pull_request_target était connu depuis longtemps comme un pattern risqué, mais n’avait pas été audité
    • Les références flottantes de third-party actions comme @v6.0.2 et @main créent en permanence un risque de supply chain, indépendamment de cet incident
    • En raison de la politique de npm selon laquelle il est impossible de faire un unpublish s’il existe des dépendants, l’unpublish a été impossible pour presque tous les paquets touchés
    • Il a fallu dépendre de npm security pour supprimer les tarballs côté registry, ce qui a ajouté plusieurs heures pendant lesquelles les tarballs malveillants restaient installables
    • La liste de 7 maintainers du scope npm signifie 7 cibles distinctes de vol de credentials pour un même blast radius
    • Le binding OIDC trusted-publisher ne prévoit pas de review à chaque publication et, une fois configuré, n’importe quel code path dans le workflow peut mint un token autorisé à publier
    • L’alternative nécessaire consiste à passer à des classic tokens de courte durée avec review manuelle, ou à ajouter une provenance-source-verification capable de détecter les publications issues d’étapes inattendues du workflow
  • Ce qui a joué en leur faveur

    • L’attaquant a choisi un payload qui cassait les tests, ce qui a fait sauter l’étape normale de publication et a empêché la génération d’un tarball à l’apparence plus propre
    • Cela a rendu l’attaque suffisamment bruyante pour être détectée rapidement
    • Un attaquant plus prudent, qui n’aurait pas cassé les tests, aurait pu publier discrètement pendant plusieurs heures de plus
    • L’attaquant a réutilisé un script public de memory dump contenant un commentaire d’attribution, et n’a pas écrit de nouveau code, ce qui a accéléré le matching des IOC

Questions en suspens

  • Il faut vérifier si l’étape Setup Tools de bundle-size.yml a réellement appelé actions/cache@v5
  • Il faut le valider en lisant un log post-job de l’un des runs pull_request_target sur la PR #7378 ; un exemple de run id est 25666610798
  • Il faut vérifier ce que contenait le commit head initial de la PR avant qu’il ne disparaisse via force-push ; cela pourrait subsister dans le reflog GitHub
  • Il faut déterminer si le commit malveillant est entré dans le git object store du fork via un git push direct, ou via une création dans l’interface web GitHub qui aurait laissé une entrée dans l’audit log
  • Il faut vérifier si voicproducoes est un vrai compte ou un sock puppet en comparant avec son historique d’activité
  • Il faut vérifier si le cache npm, visible sous la forme de 6 entrées dupliquées linux-npm-store-*, a lui aussi été contaminé et s’il a réellement été utilisé
  • Il faut vérifier si l’attaque nécessitait Nx Cloud, ou si elle aurait aussi fonctionné avec le seul cache GitHub Actions
  • Il faut vérifier s’il est possible d’identifier, dans le réseau de forks de TanStack/router, d’autres forks contenant le commit de payload orphelin
  • Si d’autres forks hébergent ce commit, l’accessibilité via github:tanstack/router#79ac49ee... resterait possible, ce qui compliquerait davantage le nettoyage
  • Il faut auditer si d’autres dépôts TanStack comme router, query, table, form ou virtual utilisent le même style de pattern bundle-size.yml
  • Il faut obtenir auprès du support npm le nombre d’utilisateurs ayant effectivement téléchargé les versions affectées pendant la fenêtre de publication
  • Il faut vérifier si les machines des 7 maintainers ont été compromises séparément
  • Les publications malveillantes n’ont pas utilisé de token npm de maintainer, mais les machines des maintainers peuvent avoir été des cibles secondaires de la logique d’auto-propagation

Références

1 commentaires

 
GN⁺ 2 시간 전
Commentaires sur Hacker News
  • Il faut faire attention au moment de révoquer un token. La charge utile semble installer un dead-man's switch dans ~/.local/bin/gh-token-monitor.sh, puis l'enregistrer comme service utilisateur systemd sous Linux et comme LaunchAgent com.user.gh-token-monitor sur macOS
    Il interroge api.github.com/user toutes les 60 secondes avec le token volé, et si le token est révoqué et renvoie un HTTP 40x, il exécute rm -rf ~/
    https://github.com/TanStack/router/issues/7383#issuecomment-...

    • En pratique, si un malware a été installé, il faut de toute façon réinitialiser complètement la machine
    • Hallucinant. C'est une situation de destruction mutuelle assurée
      Le monde du logiciel risque d'être vraiment brutal pendant les 5 prochaines années, et les systèmes air-gapped vont probablement devenir très importants
    • Il aurait toujours fallu avoir des sauvegardes, mais si cet incident pousse les gens à s'en équiper, c'est déjà ça
  • Le paquet npm @mistralai/mistralai a lui aussi été compromis dans le cadre de ce ver
    https://github.com/mistralai/client-ts/issues/217
    Il a depuis été retiré du registre npm

  • C'est regrettable, mais cela semble montrer que le Trusted Publishing ne suffit pas, à lui seul, pour publier en toute sécurité depuis une CI. Un attaquant présent dans le pipeline CI ou disposant de droits admin volés sur le dépôt peut publier très facilement
    Ce n'est pas nouveau, et Trusted Publishing n'a pas été conçu pour garantir cela, mais passer de publications locales avec authentification à deux facteurs à Trusted Publishing introduit ce vecteur d'attaque via une compromission de la CI. En local, le deuxième facteur qui empêchait npm publish disparaît
    D'après les éléments connus, l'attaquant a pris le contrôle du pipeline CI/CD et, comme npm publish n'avait pas de deuxième facteur, il a pu voler un token OIDC et finaliser la publication. Fait intéressant mais distinct, le job de publication lui-même a échoué, mais la charge utile dans le commit malveillant semble avoir pu se publier elle-même à l'aide du token OIDC du workflow
    Ce qu'il faudrait, c'est conserver le modèle Trusted Publisher sans token longue durée, tout en gardant un deuxième facteur hors de GitHub pour les déploiements CI. Autrement dit, il faudrait un déploiement par étapes où quelqu'un, côté npm, doit promouvoir l'artifact en publication effective via une authentification à deux facteurs
    Si le déploiement ne peut se faire qu'à l'intérieur du modèle de confiance de GitHub, alors toute personne qui dérobe un token d'admin du dépôt ou injecte du code malveillant dans le pipeline peut facilement mener la publication à son terme. Avec un vrai deuxième facteur hors du contexte GitHub, on peut toujours saboter le dépôt ou y injecter du code malveillant, mais pas publier sans ce deuxième facteur côté registre

    • J'ai un paquet semi-populaire, et j'utilise toujours la publication locale avec authentification à deux facteurs. Trusted Publishing a l'air trop complexe et semble se faire pirater en permanence, donc je me demande si ce n'est pas trop complexe pour être exploité en sécurité chez nous, au point qu'il faudrait peut-être le repenser de zéro
    • Je pense toujours que le Trusted Publishing est une grosse amélioration, mais l'idée d'exiger un deuxième facteur au moment de marquer une release comme réellement publique est bonne. Cela rendrait ce type de ver CI très difficile à exécuter
    • J'aimerais faire une signature avec contact physique via une YubiKey. L'idée même de faire confiance au cloud pour gérer les identifiants à notre place ressemble à une erreur
    • Le blog d'astral a récemment montré comment utiliser Trusted Publishing tout en gardant un release gate, c'est-à-dire une approbation manuelle dans le workflow de release. Malheureusement, la documentation Trusted Publishing de NPM/PyPI/Rubygems ne mentionne même pas cette possibilité et ne l'offre pas par défaut
    • Je n'ai jamais bien compris pourquoi certains disent que le Trusted Publishing change quoi que ce soit face à ce type d'attaque de la supply chain
  • Post-mortem : https://tanstack.com/blog/npm-supply-chain-compromise-postmo...

    • Merci à TanStack pour ce post-mortem, mais j'ai l'impression que les problèmes de sécurité à l'échelle de tout l'écosystème npm restent une inquiétude bien réelle
      Je me demande s'il existe des preuves montrant que les sous-paquets ayant pu importer ou embarquer des paquets TanStack peuvent être considérés comme sûrs
  • Les scripts postinstall sont catastrophiques. Tout le monde devrait utiliser pnpm
    Il est absurde qu'un commit « orphelin » poussé sur un FORK puisse déclencher ce genre de chose dans le client npm. À mon avis, GitHub porte aussi une grande part de responsabilité. Le fait qu'un commit issu d'un fork malveillant soit accessible, via le stockage d'objets partagé de GitHub, par une URI indifférenciable de celle d'un dépôt légitime est une conception complètement folle

    • Si vous lancez l'application avec des dépendances mises à jour, ce code s'exécute de toute façon. Que ce soit root ou non-root importe peu ; ce qui compte, c'est que les éléments sensibles sont accessibles avec les droits de l'utilisateur qui exécute l'application
    • Je ne comprends pas comment cela ne constitue pas un incident P0 chez GitHub. Quelqu'un peut l'expliquer ?
      En lisant ça la première fois, j'ai cru qu'ils employaient mal le mot « fork » et qu'ils parlaient en fait d'une branche du dépôt officiel. Je me suis dit que ce n'était pas possible, et pourtant si
  • https://tanstack.com/blog/npm-supply-chain-compromise-postmo...
    TanStack vient de publier son post-mortem sur cet incident

  • Un rappel pour configurer son environnement npm de manière sûre
    https://gajus.com/blog/3-pnpm-settings-to-protect-yourself-f...
    Quelques réglages suffisent à réduire fortement le risque

    • À partir de npm v11, il existe aussi allow-git=none : https://github.blog/changelog/2026-02-18-npm-bulk-trusted-pu...
    • J'ai l'impression que cet article se trompe sur l'âge minimal de release dans npm. 1) Le nom du paramètre est min-release-age. 2) Pour une raison obscure, il a été défini en jours et non en minutes : https://docs.npmjs.com/cli/v11/using-npm/config#min-release-...
      Je trouve que l'univers des gestionnaires de dépendances est fragmenté de manière totalement inutile
    • Affirmer qu'en réglant l'âge minimal à 7 jours on ne subira « jamais » de vulnérabilité de supply chain sur npm est exagéré
    • Il faut absolument épingler toutes les dépendances
      Si vos dépendances de version de paquet sont du type ^1.0.0 ou même "*", inutile de lire la suite : il faut immédiatement les figer vers des versions sûres
  • J'ai bricolé ça rapidement avec Claude pour aider à freiner la propagation. Il faut évidemment vérifier par soi-même, mais l'outil scanne la machine pour voir si les paquets compromis mentionnés s'y trouvent : https://github.com/PaulSinghDev/tanstack-shai-hulud-fix

  • On dirait qu'on est arrivé au point où tout le monde devrait exécuter chaque projet dans une VM dédiée
    Vu les récentes vulnérabilités d'escalade de privilèges en local, Docker ne suffit clairement pas. De toute façon, les conteneurs n'ont jamais été conçus comme frontière de sécurité principale

    • Les Devcontainers sont probablement la forme la plus connue de cet « environnement de développement isolé », mais ce ne sont pas des VM complètes et ils n'auraient pas totalement protégé dans ce cas précis. Les identifiants GitHub sont automatiquement injectés dans le conteneur
      Et si d'autres services cloud doivent être accessibles depuis l'intérieur du conteneur, ce voleur d'identifiants les récupérera aussi. Cela dit, cela réduit quand même le rayon d'impact, donc c'est au moins une amélioration
    • QubesOS va dans la bonne direction. On finit par vouloir plusieurs VM à la racine et des couches de sécurité superposées
    • Si vous tenez vraiment aux conteneurs, une option est aussi d'avoir une VM par conteneur. Le fait de tout faire tourner dans des VM, plutôt que sur des services Kubernetes arbitraires, m'a rendu assez serein ces dernières semaines
    • Heureusement, les projets qui utilisent des écosystèmes de langages plus sûrs comme C et C++ sont à l'abri de ce problème :-)
  • Waouh, encore un paquet énorme. Je republie l'avertissement d'intérêt public que j'avais posté après la compromission d'Axios et de LiteLLM. Ce qui concerne les scripts de cycle de vie s'applique ici aussi
    npm/bun/pnpm/uv prennent désormais tous en charge le réglage d'un âge minimal de release pour les paquets. J'ai aussi mis ignore-scripts=true dans ~/.npmrc, et d'après l'analyse cela aurait suffi à atténuer cette faille. bun et pnpm n'exécutent pas les scripts de cycle de vie par défaut
    Voici comment définir globalement un âge minimal de release de 7 jours
    ~/.config/uv/uv.toml
    exclude-newer = "7 days"
    ~/.npmrc
    min-release-age=7 # days
    ignore-scripts=true
    ~/Library/Preferences/pnpm/rc
    minimum-release-age=10080 # minutes
    ~/.bunfig.toml
    [install]
    minimumReleaseAge = 604800 # seconds
    Si vous devez neutraliser ce réglage globalement, vous pouvez utiliser les flags CLI
    npm install --min-release-age 0
    pnpm add --minimum-release-age 0
    uv add --exclude-newer "0 days"
    bun add --minimum-release-age 0
    J'ajouterais encore une chose : certains craignent qu'une adoption massive d'un délai d'attente sur les dépendances retarde la découverte des vulnérabilités, ou constitue une forme de passager clandestin, mais je ne suis pas d'accord. Ce qu'on échange contre un délai d'attente sur les dépendances, c'est une préférence temporelle, et il y aura toujours des gens avec une préférence temporelle plus élevée que la mienne
    0: https://news.ycombinator.com/item?id=47582220
    1: https://news.ycombinator.com/item?id=47513932

    • D'accord. Heureusement, j'avais activé ces réglages en mars, avant les deux dernières vagues. En plus, il faut committer le lockfile dans le dépôt et rester vigilant lorsqu'on ajoute de nouvelles dépendances
      Pour éviter les changements imprévus, il suffit d'utiliser pnpm install --frozen-lockfile. Et si min-release-age n'est pas configuré, il faut se rappeler que des paquets affectés peuvent aussi être remontés via des dépendances transitives. Si possible, il vaut mieux aussi figer la version du gestionnaire de paquets lui-même