Aller au contenu principal

Attaques supply chain sur NuGet : une analyse de risque

Nom, popularité, dépôt, mainteneur, ancienneté : chaque indicateur de confiance instinctif a fait l'objet d'une falsification documentée sur NuGet. Analyse de risque structurée sur la méthode EBIOS RM, cas documentés à l'appui.

Ajouter un package NuGet, c'est faire un choix rapide à partir d'indices imparfaits : un nom, un mainteneur, un dépôt, un nombre de téléchargements. Dans la majorité des cas, ce choix est banal et fonctionne. Mais c'est justement cette normalité qui rend l'écosystème exploitable : les attaques supply chain documentées sur NuGet ne cassent pas les mécanismes de sécurité, elles trompent les signaux sur lesquels repose la confiance. Cet article examine ce risque, les scénarios documentés qui le matérialisent et ce que cela change pour une équipe .NET.

Un second article, évaluer un package NuGet, propose une grille d'analyse avant intégration. Un troisième, en préparation, traitera de la gouvernance des dépendances dans une équipe.

Cadrage : l'objet étudié et la méthode

L'objet étudié est la décision d'utiliser un package NuGet public, et tout ce qui en dépend. Pour rendre l'analyse concrète, on prend le cas courant d'une équipe .NET qui développe et livre une application métier, consomme ses dépendances depuis nuget.org, et compile sur les postes des développeurs comme dans la chaîne d'intégration continue.

La structure reprend la logique de la méthode EBIOS Risk Manager de l'ANSSI : identifier ce qui peut être perdu, qui pourrait provoquer cette perte et par quels scénarios. Une attaque supply chain ne vise pas l'application frontale ; elle vise un composant de confiance pour faire entrer du code adverse par le canal habituel. Le CERT-FR suit ces campagnes au niveau national : la vague npm dite Shai-Hulud de novembre 2025, avec plus de 700 paquets touchés par auto-réplication, a fait l'objet d'un suivi dédié. Le sujet n'a donc rien de théorique.

Il ne s'agit pas d'une analyse EBIOS RM complète, qui partirait des valeurs métier d'une organisation donnée. C'est un cas générique, pensé pour être adapté : chaque équipe pondérera les événements redoutés selon son contexte.

Ce qu'une équipe risque concrètement

Un événement redouté, au sens EBIOS, est une atteinte à ce qui a de la valeur pour l'équipe. Chaque ligne ci-dessous s'appuie sur au moins un cas documenté sur NuGet.

Événement redouté Ce qui est perdu Cas documenté
Exfiltration de secrets Clés d'API, certificats, portefeuilles, identifiants présents sur les postes et dans la CI Clés de portefeuilles crypto (Netherеum.All), certificats PFX (Sicoob.Sdk), tokens d'API de paiement (StripeApi.Net)
Exécution de code sur les postes et la CI Intégrité de l'environnement de développement et de build Cibles MSBuild auto-exécutées à la compilation, vecteur documenté depuis 2020 (NuGet/Home#10262)
Compromission des livrables Intégrité de ce que l'équipe livre à ses propres clients : l'équipe devient elle-même le vecteur Conséquence structurelle de toute dépendance compromise embarquée dans un livrable
Sabotage de la disponibilité Disponibilité de l'application, immédiatement ou des années après l'intégration selon la charge Packages du compte shanhai666 : sabotage de bases de données programmé pour 2027-2028, et sabotage immédiat des automates Siemens S7 par le typosquat Sharp7Extend
Impact juridique et réputationnel Conformité (RGPD si données personnelles exfiltrées), confiance des clients, responsabilité contractuelle Conséquence dérivée des événements précédents

La gravité relative de ces événements dépend du contexte : une équipe qui manipule des secrets de production sur les postes de développement n'a pas le même profil qu'une équipe dont la CI est isolée. C'est cette pondération qui relève de l'analyse propre à chaque organisation.

Qui attaque, et pourquoi

Les cas documentés sur NuGet couvrent trois profils de sources de risque, aux objectifs distincts :

  1. L'opportuniste à but lucratif immédiat. Il cible les secrets monnayables : portefeuilles crypto, tokens d'API de paiement. Les cas Netherеum.All et StripeApi.Net relèvent de ce profil : peu d'investissement, ciblage large, monétisation directe.
  2. Le ciblage sectoriel. Il vise un écosystème précis : intégrateurs bancaires brésiliens (Sicoob.Sdk), utilisateurs de bibliothèques d'entreprise chinoises (bmrxntfj), systèmes de contrôle industriel (packages du compte shanhai666). L'investissement est plus élevé, la cible plus étroite, et l'objectif peut relever du renseignement ou du sabotage.
  3. Le patient qui construit un capital de confiance. C'est le profil le plus difficile à détecter : cinq ans d'historique cohérent pour Tracer.Fody.NLog, tentative de captation de réputation à grande échelle en janvier 2026 (détaillée plus bas). L'attaque n'est pas dans le package du jour ; elle est dans la position acquise pour demain.

Les scénarios : chaque indicateur de confiance et sa falsification

Lorsqu'un développeur choisit un package, il s'appuie souvent sans le formuler sur quelques indices : un nom connu, des téléchargements nombreux, un dépôt GitHub, un mainteneur établi. Chaque scénario ci-dessous prend l'un de ces indices et montre, cas documenté à l'appui, comment il a été falsifié. C'est le cœur de l'analyse : le risque ne vient pas d'un défaut des indicateurs, mais de la confiance qu'on leur accorde alors qu'ils restent falsifiables à faible coût.

Le nom que je lis

L'indicateur : "ce nom est celui du package que je connais". Sa falsification : le typosquatting par variation ASCII, et l'homoglyphe, indétectable visuellement. Le cas Netherеum.All (Socket, octobre 2025) substitue un "е" cyrillique (U+0435) au "e" latin du client Ethereum Nethereum. Cette falsification était rendue possible par une caractéristique du registre : nuget.org validait les identifiants avec une expression régulière Unicode-inclusive, visible dans PackageIdValidator.cs, là où npm et PyPI restreignent les noms à l'ASCII. NuGet a annoncé fermer ce vecteur pour les nouveaux packages (voir le traitement du risque) ; les identifiants homoglyphes déjà publiés, eux, restent en place. Le typosquatting par variation ASCII, lui, n'est couvert par aucune de ces mesures.

La popularité que je constate

L'indicateur : "des millions de téléchargements, donc une adoption qui vaut validation". Sa falsification : l'inflation par scripting, sans mécanisme côté nuget.org qui l'empêche en pratique. Netherеum.All affichait 11,6 millions de téléchargements générés en quelques jours. La contre-mesure intuitive, regarder la trajectoire plutôt que le volume, a elle-même déjà été contournée : le cas StripeApi.Net (ReversingLabs, février 2026) répartit environ 180 000 téléchargements artificiels sur 506 versions, soit près de 300 par version, pour simuler une progression organique. La falsification s'adapte aux heuristiques de détection à mesure qu'elles se diffusent.

Le dépôt que je vérifie

L'indicateur : "le code est sur GitHub, je peux le lire, l'historique est ancien". Sa falsification prend deux formes. D'abord, la façade clean-source : le dépôt publié est propre, mais la charge ne vit que dans la DLL distribuée sur NuGet, et le champ dépôt, purement déclaratif, ne relie rien de manière vérifiée. Le cas Sicoob.Sdk (Socket, mai 2026) exfiltrait des certificats bancaires avec une organisation GitHub créée la veille de la première publication et un compte contributeur créé environ deux minutes avant l'organisation elle-même. Ensuite vient l'antidatage : les timestamps git sont des données client, acceptées sans validation par les forges ; deux ans d'historique se fabriquent en quelques heures, et le récit du "projet interne rendu public" suffit alors à masquer l'absence de trace externe datée.

Le mainteneur en qui j'ai confiance

L'indicateur : "ce publisher est établi, ses packages sont sûrs". C'est sans doute le plus précieux, donc le plus attaqué. Sa falsification a une dimension temporelle : l'identité peut être vraie aujourd'hui et compromise demain. Trois variantes documentées ou activement tentées sur NuGet :

  • L'imitation d'identité. Le cas Tracer.Fody.NLog (Socket, décembre 2025) typosquatte le nom du publisher plutôt que celui du package. L'historique a été patiemment construit pendant cinq ans, tandis que la malveillance ne vit que dans le code compilé.
  • La captation de réputation. En janvier 2026, des milliers de mainteneurs NuGet ont reçu des invitations à devenir co-owners d'un package TestPackage.Security.Research ou à rejoindre une organisation, depuis un compte sans historique. L'objectif documenté par les mainteneurs ciblés, dont Andrew Gubskiy : si un mainteneur connu accepte, le compte attaquant acquiert instantanément un statut de confiance, exploitable plus tard pour distribuer du code malveillant sous couvert de légitimité. L'attaque ne vise pas du code : elle vise le modèle de confiance lui-même.
  • La prise de contrôle de compte. Un mainteneur inactif devient une cible évidente : l'attaquant qui prend le contrôle du compte publie une version compromise en héritant de toute la confiance accumulée. C'est le vecteur que la 2FA obligatoire, généralisée par nuget.org depuis 2022, vise directement ; les écosystèmes voisins l'ont appris à leurs dépens (incidents ua-parser-js et event-stream sur npm, documentés dans la taxonomie de menaces du framework S2C2F).

Les analyses qui m'ont précédé

L'indicateur : "ce package existe depuis des mois, les scanners l'auraient signalé". Sa falsification : la rotation de versions. Le compte bmrxntfj (Socket, mai 2026), cinq packages imitant des bibliothèques .NET chinoises, a maintenu 219 des 224 versions publiées non répertoriées, une seule version visible à la fois par package, ce qui invalide les indicateurs de compromission fondés sur les hashes des versions déjà analysées, pour environ 65 000 téléchargements sur au moins sept mois. Le comportement du registre qui rend cette rotation possible : un package non répertorié reste installable par ID et version exacte, un choix conçu pour ne pas casser les builds existants.

Le traitement du risque

Dans une analyse de risque, les scénarios appellent des mesures. On peut les lire à trois niveaux : registre, développeur, organisation.

Côté registre

Plusieurs mesures existent déjà, et d'autres progressent :

  • 2FA obligatoire depuis 2022, à 100% d'adoption chez les mainteneurs actifs selon le bilan de sécurité NuGet de juillet 2024. Elle réduit la prise de contrôle de comptes existants.
  • Trusted publishing depuis septembre 2025. Elle renforce le lien entre le pipeline de build et la publication.
  • Restriction ASCII sur les nouveaux identifiants, annoncée en juin 2026 (NuGet/Announcements#75). Elle aligne nuget.org sur npm et PyPI et ferme le vecteur homoglyphe pour les publications futures. Elle ne porte pas sur le stock existant, conservé par liste d'exception, et ne touche pas le typosquatting ASCII.

Ces mesures ferment des portes d'entrée ; elles ne détectent pas les packages malveillants déjà passés. Le bilan 2024 le reconnaît lui-même : les outils disponibles échouent à détecter les attaques supply chain en cours. La campagne suivie par ReversingLabs, avec plus de 700 packages malveillants depuis août 2023, s'est déroulée intégralement après la généralisation de la 2FA. Les scanners tiers réduisent la fenêtre d'exposition sans l'annuler : quatre jours pour Netherеum.All, sept mois pour bmrxntfj.

Côté développeur

La réponse côté développeur est l'évaluation au moment du choix : c'est l'objet de l'article suivant, qui reprend chaque indicateur falsifiable de cette analyse et lui substitue des signaux plus coûteux à falsifier.

Côté organisation

La structuration de la décision et son suivi dans le temps relèvent de la gouvernance des dépendances. Pour une démarche de maturité complète côté consommation, le framework S2C2F (initié par Microsoft, porté par l'OpenSSF) fournit un modèle en huit pratiques et quatre niveaux, construit sur une taxonomie de menaces qui recoupe celle de cet article ; le guide d'évaluation OpenSSF en est le pendant concis côté sélection.

Limites

  • Cette analyse est générique, pas contextualisée. Une analyse EBIOS RM réelle part des valeurs métier de l'organisation et pondère les événements redoutés en conséquence. Le cas-type retenu ici est un dénominateur commun, pas un substitut à cette pondération.
  • Les cas documentés sont ceux qui ont été détectés. Le biais de survie est inévitable : les attaques réussies non détectées n'apparaissent dans aucun rapport. Le paysage réel est au moins aussi vaste que le paysage documenté.
  • Les indicateurs de falsification évoluent. Le cas StripeApi.Net montre une adaptation directe aux heuristiques de détection diffusées publiquement. Chaque cas cité est daté ; les comportements du registre décrits sont ceux constatés au moment de la rédaction.
  • L'analyse s'arrête au périmètre NuGet public. Les flux privés et la confusion de dépendances, les compromissions d'outils de build et les attaques sur l'infrastructure de CI sont des scénarios réels, hors du périmètre de ce dossier.

Conclusion

Le résultat central tient en une phrase : chaque indicateur sur lequel repose la confiance instinctive dans un package (le nom, la popularité, le dépôt, le mainteneur, l'ancienneté) a déjà fait l'objet d'une falsification documentée sur NuGet, à faible coût au regard des événements redoutés. La réponse n'est pas de renoncer aux packages, mais de remplacer des indicateurs falsifiables par une évaluation fondée sur des signaux plus coûteux à tromper : c'est l'objet de la suite du dossier.

Cet article décrit des mécanismes d'attaque documentés publiquement, dans l'état constaté à la date de rédaction. Les cas cités renvoient aux rapports d'analyse originaux ; les packages concernés ont été retirés de nuget.org et ne sont plus vérifiables directement.

Ressources

Vous souhaitez faire monter en compétence vos développeurs ?

Je propose des formations techniques et de l'accompagnement de projets.

Discuter de votre besoin

Articles connexes

NuGet : évaluer un package avant de l'intégrer

Trouver un package qui répond à un besoin est facile. Construire une opinion défendable sur sa fiabilité l'est moins. Une grille de signaux observables et un processus pour décider avant d'intégrer.