1 points par GN⁺ 1 시간 전 | 1 commentaires | Partager sur WhatsApp
  • Une attaque de la chaîne d’approvisionnement du registre npm a exposé des millions d’applications d’entreprise et des milliards d’enregistrements d’utilisateurs, mais l’écosystème l’accepte comme si c’était inévitable
  • Le Senior Frontend Engineer Mark Vance épingle la réalité d’un monde où, même pour mettre une chaîne en majuscules, on dépend de 40 niveaux de dépendances imbriquées provenant de paquets non vérifiés
  • La compromission d’un paquet utilitaire abandonné de longue date, injectant un crypto-miner dans des builds de production à l’échelle mondiale, est traitée comme une catastrophe naturelle
  • L’écosystème Node.js considère l’exécution de code à distance malveillante comme une tragédie imprévisible, tandis que les équipes DevOps s’acharnent à faire tourner les clés AWS
  • Les écosystèmes Go, Rust et les Web API natives servent de contrepoint, avec de solides bibliothèques standard et une vérification cryptographique qui réduisent la dépendance à des composants tiers

Satire d’une attaque de la chaîne d’approvisionnement npm

  • Une attaque de la chaîne d’approvisionnement du registre npm a compromis des millions d’applications d’entreprise et exposé des milliards d’enregistrements d’utilisateurs, mais les développeurs de l’écosystème JavaScript la considèrent comme quelque chose qu’« on ne pouvait absolument pas éviter »
  • Le Senior Frontend Engineer Mark Vance voit comme le prix du développement d’applications web modernes le fait de dépendre d’un arbre de 40 niveaux de dépendances imbriquées issues de paquets non vérifiés pour simplement mettre une chaîne unique en majuscules
  • Le détournement d’un paquet utilitaire laissé à l’abandon, conduisant à l’injection d’un crypto-miner dans des builds de production partout dans le monde, est traité comme une catastrophe naturelle
  • L’écosystème Node.js présente l’exécution de code à distance malveillante comme une tragédie imprévisible et adresse ses « pensées et prières » aux équipes DevOps occupées à remplacer les clés AWS

Le contraste entre npm et les autres écosystèmes

  • Les écosystèmes Go, Rust et les Web API natives réduisent fortement la dépendance au code tiers grâce à de solides bibliothèques standard et intègrent une vérification cryptographique stricte dans leurs toolchains essentielles
  • Le contraste est présenté de façon à dire que, dans ces écosystèmes, le nombre d’incidents où « le projet de week-end d’un étudiant décrocheur détruit une infrastructure logistique mondiale » était de 0 aujourd’hui
  • Un porte-parole de npm affirme que, dans un monde où des acteurs malveillants existent, il faut simplement l’accepter, et qu’il n’existe ni politique de registre ni garde-fous de sandbox de build capables de l’empêcher
  • Le registre npm est décrit comme un registre open source qui exécute par défaut des scripts d’installation arbitraires sur les machines locales, ce qui fait écho à la déclaration du porte-parole et au risque structurel
  • La conclusion exprime sa compassion pour les victimes tout en disant qu’il faut rester résilient jusqu’à « la prochaine compromission inévitable demain matin »

1 commentaires

 
GN⁺ 1 시간 전
Commentaires sur Hacker News
  • Chacun aura son avis sur la période de cooldown, mais une bonne partie des récentes attaques sur la supply chain npm, dont axios et tanstack, auraient probablement pu être évitées avec un cooldown
    Si vous utilisez Artifactory / Nexus, il y a de fortes chances qu’un cooldown soit déjà en place, et sinon c’est facile à configurer
    La plupart des compromissions de npm ou PyPI ont été retirées en quelques heures, donc l’idée du cooldown est simplement « ignorer les paquets publiés depuis moins de N jours ». Même 1 jour aide, 3 jours c’est correct, et 7 jours est un peu excessif mais fonctionne
    Pour le configurer, on peut soit utiliser une version récente de pnpm avec un cooldown par défaut d’un jour https://pnpm.io/supply-chain-security, soit, si l’on veut corriger ça d’un coup, utiliser https://depsguard.com qui ajoute un cooldown et des réglages recommandés à npm, pnpm, yarn, bun, uv et dependabot. J’en suis le mainteneur
    Il y a aussi https://cooldowns.dev, davantage centré sur le cooldown, avec un script pour aider à la configuration locale. Tout est open source ou gratuit
    Si vous savez déjà éditer vous-même ~/.npmrc et consorts, ce n’est sans doute pas nécessaire, mais pour les personnes autour de vous qui ont besoin d’une solution en un clic, cela peut les aider à éviter la prochaine attaque
    En revanche, s’il faut corriger un CVE critique récent, il faut contourner le cooldown, et chaque outil a sa manière de le faire. Je n’ai pas de chiffres précis, mais ces dernières semaines, le risque semble venir davantage des attaques sur la supply chain logicielle que des nouveaux CVE zero-day

    • Je trouve presque plus étrange l’idée que 7 jours serait excessif. Sauf si une nouvelle fonctionnalité précise est indispensable, même pour démarrer un nouveau projet, une version de dépendance publiée il y a quelques mois devrait généralement suffire
      Même chose pour les mises à niveau régulières de dépendances. Il existe bien des cas où il faut monter immédiatement de version, par exemple pour répondre à une vulnérabilité, mais dans ce cas je trouverais acceptable d’obliger le développeur à sélectionner explicitement la nouvelle version voulue
    • J’ai l’impression que ça ne fait que repousser le problème de 7 jours. Ces incidents se terminent parce que quelqu’un est infecté et s’en aperçoit, pas parce qu’une armée audite les changements et les détecte, du moins c’est ce que je pensais
      Si tout le monde met un cooldown de 7 jours, est-ce que ça n’explose pas simplement plus tard ?
    • Il semble manquer une mention :

      Disclaimer: I maintain depsguard

    • Je ne suis pas certain que le cooldown soit efficace. Il faut bien que quelqu’un contourne le cooldown, installe une release potentiellement problématique et découvre le problème. Si personne ne le fait, on n’a fait que retarder le problème de 3/7/10/14 jours
      En y repensant en écrivant, je suis quand même favorable à un cooldown de 10 jours consistant à ne rien installer de publié dans les 10 derniers jours. Je pense simplement qu’il ne faut pas s’attendre à ce que ce soit l’unique mesure d’atténuation
    • Pourquoi ne pas créer, comme pour les distributions Linux, des distributions ou canaux séparés de type latest/stable/LTS ?
  • Je me demande ce que Go ou Rust garantissent réellement de plus que Python/npm. On dirait aussi que Python/npm sont simplement des cibles plus appétissantes
    J’essaie de plus en plus d’éviter tous les paquets tiers

    • La manière d’attribuer la propriété des paquets et des espaces de noms dépend à 100 % de l’entité qui exploite le gestionnaire de paquets
      Maven Central existe depuis des décennies, et il y a eu très peu d’incidents de vol d’espace de noms
      Impossible de publier un paquet avec le groupId com.ycombinator sans vérification de la propriété du domaine ycombinator.com. Et une fois publié, un paquet est 100 % immuable, même s’il contient du code malveillant. Bien sûr, une telle bibliothèque est ensuite signalée comme vulnérable un peu partout
      Je ne comprends pas comment NPM n’a pas réussi, après tout ce temps, à reproduire des garde-fous comme ceux de Maven Central
    • L’un des points essentiels de l’article est que la plupart des autres langages populaires disposent d’une bibliothèque standard complète. Celle de JS est étonnamment petite
      Au lieu d’avoir un ensemble de bibliothèques validées distribuées avec le langage, les applications doivent soit les écrire elles-mêmes, soit les récupérer dans un dépôt tiers. Comme on a longtemps appris à éviter le NIH, les gens ont tendance à prendre un paquet
      Ce n’est pas forcément mauvais en soi, mais cela attire souvent plus de code que nécessaire. L’écosystème JS privilégie aussi les petits modules, ce qui en multiplie le nombre, puis tout le monde réempile par-dessus, et le graphe de dépendances devient énorme. Volontairement ou non, la surface de problèmes potentiels est immense
      Les autres langages offrent davantage de choses par défaut. Il y a bien eu des bugs et des problèmes de sécurité, mais c’est dérisoire comparé à ce qu’on voit dans l’écosystème JS. Le graphe de dépendances externes est bien plus petit et les fonctionnalités centrales viennent de tiers de confiance
    • Les attaquants vont là où sont les victimes. Le front-end est presque une monoculture où l’immense majorité utilise NPM, alors que c’est moins vrai côté back-end
      Ce n’est pas une excuse pour NPM, au contraire, c’est juste un facteur de plus contre lui
      On pourrait aussi dire que ces attaques montrent encore davantage la différence entre développeurs front-end et back-end, mais je n’irai pas jusque-là
    • Honnêtement, Rust présente exactement les mêmes schémas d’attaque sur la supply chain. Il est simplement plus récent et mieux administré pour l’instant. Attendez juste 10 ans
    • La dernière fois que j’ai vérifié, npm imposait la 2FA pour la publication, mais pas cargo. Je ne pense pas que cargo soit meilleur que npm, juste qu’il n’est pas une cible aussi attrayante
  • Dans plusieurs entreprises, on s’est beaucoup battu pour installer une configuration npm globale sûre sur les machines de tous les développeurs, demander aux gens de ne pas la désactiver, et vérifier cela avec des outils MDM
    Des paramètres par défaut plus sûrs auraient dû exister depuis longtemps

    • Il suffit de ne pas utiliser npm. On peut prendre un gestionnaire de paquets qui n’exécute pas postinstall par défaut, et la migration est incroyablement simple
    • Je me demande ce qu’on entend par configuration sûre. Si l’objectif est d’imposer une période de cooldown ou des listes d’autorisation/blocage de paquets, la bonne approche consiste à configurer un dépôt contrôlé par l’entreprise, qui se fournit en amont depuis le dépôt npm tout en appliquant les politiques voulues
  • Il n’existe aucune raison légitime pour que les scripts postinstall existent. L’équipe npm devrait maintenant être assez mûre pour annoncer : « à partir de telle version de npm, les scripts postinstall ne seront exécutés que pour les versions de paquets publiées avant le ${today} »

    • J’ai récemment audité plusieurs scripts postinstall de paquets populaires. La plupart servent à utiliser ou télécharger des binaires natifs, détecter la compatibilité de la plateforme, faire le raccord eux-mêmes au lieu de laisser Node amorcer cela, et contourner des problèmes de vieilles versions de npm
      C’est parce que des toolchains comme esbuild sont écrites dans des langages compilés et distribuées comme binaires via le dépôt npm. Si l’on utilise une version récente de Node/npm ainsi qu’un OS/une plateforme courants et récents, on devrait pouvoir désactiver tous les scripts postinstall sans problème légitime
    • Les scripts d’installation sont, comme les signatures de paquets, un élément de distraction. Ajouter ou retirer telle ou telle fonctionnalité n’aura pas de grand impact sur le potentiel de propagation façon ver de cet écosystème de paquets
      Le code npm installé finit presque toujours par être exécuté
    • Le fait que les paquets Rust puissent être exécutés sans sandbox lors de leur compilation n’est pas non plus très justifiable
    • Cela ne résout pas réellement le problème. Le code des paquets est aussi exécuté au moment du build et pendant les tests. On peut réduire un peu la portée, mais pas davantage
    • Pour le dire avec prudence, les scripts postinstall sont presque entièrement un faux sujet. Ce qui surprend, c’est que du code contrôlé par d’autres s’exécute sur ma machine et puisse faire de mauvaises choses ; et oui, c’est possible
      Mais le code ordinaire du paquet aussi. Même s’il n’est pas exécuté à l’installation, quelque chose dedans finira bien par l’être. Sinon, ce ne serait pas une dépendance au départ
      Croire que supprimer les scripts postinstall aura autre chose qu’un effet momentané sur le taux d’exploitation montre qu’on n’a pas poussé la réflexion jusqu’au bout. Malheureusement, le problème est bien plus subtil que ne le laisse entendre l’article d’origine
      Ce n’est pas une question du type « ne mettons pas le bouton qui fait tomber les ailes à côté de l’interrupteur », le cœur du problème est plutôt qu’il n’existe aucun moyen, sans travail manuel extrêmement pénible, de distinguer « le mauvais code de quelqu’un d’autre qui s’exécute sur ma machine » de « le bon code de quelqu’un d’autre qui s’exécute sur ma machine ». Et c’est précisément pour éviter ce travail pénible qu’on exécute le code d’autrui
  • Tous les projets Node.js commencent par npm install, et soudain on se retrouve avec 500 paquets qu’on n’a jamais demandés. La moitié n’a pas été touchée depuis des années

  • Il y a un problème culturel à vouloir mettre à jour vers les paquets les plus récents même quand ce qui existe déjà fonctionne très bien. Parfois les gens ne lisent même pas les notes de version pour voir si le changement les concerne
    Le cooldown n’est qu’un moyen d’imposer un peu de patience aux mainteneurs, et en pratique cela aide

    • Lorsqu’il y a des exigences de conformité, il faut mettre à jour à cause du flot de CVE touchant les anciennes versions. La plupart sont quasi factices, du genre « ReDoS sur une regex », mais il faut satisfaire la procédure, donc on met à jour quand même
    • Et puis il y a aussi le cas où les propriétaires de paquets mettent à jour des choses qui n’en ont pas besoin pour éviter de donner l’impression qu’elles sont anciennes et abandonnées
      Un paquet Lisp peut rester utilisable 15 ans sans changement, alors qu’un paquet JS est traité comme un problème grave s’il n’a pas été maintenu. Même s’il était déjà terminé il y a 15 ans, on augmente quand même la version en n’ajoutant rien, ou parfois en introduisant des changements cassants, simplement pour avoir l’air géré sur npm et GitHub. Et ensuite tout le reste se met à jour
  • Un cooldown de 7 jours ressemble à un pansement facile à appliquer avec peu d’effort. La vraie solution serait probablement du build reproductible avec des attestations signées, mais la plupart des équipes ne paieront pas ce coût avant d’avoir déjà été frappées

  • On dirait un article de The Onion

    residents of the Node.js ecosystem stood unified in their belief that the malicious remote-code execution was a completely unpredictable tragedy
    Est-ce que quelqu’un croit vraiment à cette thèse ? Il y a eu bien trop de contre-exemples
    C’est une bonne satire des échecs de l’écosystème, mais au final cela reste du divertissement. Peut-être même une occasion pour les marketeux de pousser leurs produits. Par exemple, le mainteneur de depsguard a supprimé puis rajouté, puis re-supprimé cette information dans son propre article. Au moment où j’écris, ce post est tout en haut

  • Ce lien est une version manifestement blanchie par l’IA d’une blague que Xe Iaso traîne depuis longtemps. C’est dommage
    https://xeiaso.net/shitposts/no-way-to-prevent-this/CVE-2024...
    https://news.ycombinator.com/item?id=40438408