Retour aux articles
Supply chain : comment vos dépendances npm sont devenues la principale porte d'entrée des attaquants
SécuritéDev10 juin 20254 min de lecture

Supply chain : comment vos dépendances npm sont devenues la principale porte d'entrée des attaquants

XZ Utils, event-stream, la faille SolarWinds : les attaques sur la chaîne d'approvisionnement logicielle se multiplient. Comment elles fonctionnent, pourquoi elles sont si difficiles à détecter, et les outils concrets pour s'en protéger.

En mars 2024, un développeur Microsoft remarque que son client SSH est légèrement plus lent que d'habitude. En creusant, il découvre une backdoor sophistiquée dans XZ Utils, une bibliothèque de compression présente sur presque toutes les distributions Linux. L'attaquant avait passé deux ans à gagner la confiance des mainteneurs avant d'introduire le code malveillant. C'est l'une des attaques supply chain les plus sophistiquées jamais documentées, et ce n'est pas un cas isolé.

Qu'est-ce qu'une attaque supply chain ?

Une attaque supply chain ne cible pas directement votre application. Elle cible quelque chose dont votre application dépend : une bibliothèque, un outil de build, un provider CI/CD, une image Docker. L'objectif est de compromettre un maillon de la chaîne qui touche des milliers de projets en aval.

La surface d'attaque est immense. Un projet Next.js typique a entre 800 et 1 500 dépendances transitives. Chacune est un point d'entrée potentiel. Et la plupart sont maintenues par une seule personne, bénévolement, sans audit de sécurité systématique.

Les trois patterns d'attaque les plus courants

Le typosquatting consiste à publier un package avec un nom proche d'une bibliothèque populaire (colourama au lieu de colorama, reqeusts au lieu de requests). Il suffit que quelqu'un copie une commande d'un tutoriel avec une faute de frappe pour l'installer.

Le takeover de compte mainteneur exploite le fait que de nombreux packages populaires sont liés à des comptes avec des mots de passe faibles ou des emails expirés. L'attaquant prend le contrôle du compte, publie une nouvelle version avec un payload malveillant. C'est ce qui s'est passé avec event-stream en 2018 : un développeur malveillant a proposé de reprendre la maintenance d'un package délaissé, avant d'y injecter du code volant des wallets Bitcoin.

La confusion de dépendances (dependency confusion) exploite la priorité qu'npm et pip donnent aux registres publics sur les registres privés. Si votre entreprise utilise un package interne appelé mon-package-interne, un attaquant peut publier un package du même nom sur npm avec un numéro de version plus élevé. npm l'installera à la place du vôtre.

Pourquoi c'est si difficile à détecter

Le code malveillant est rarement dans le fichier principal du package. Il se cache dans un script postinstall, dans un fichier de configuration, dans une dépendance transitive de troisième niveau. Les outils classiques comme npm audit ne cherchent que les CVE connues et référencées dans des bases de données : ils sont aveugles face à un package malveillant nouveau qui n'a encore aucun signalement.

L'attaque XZ Utils a tenu deux ans parce que le code malveillant était fragmenté, obfusqué, et activé uniquement dans des conditions très spécifiques (architecture x86, version de glibc précise, environnement systemd). Même des yeux experts l'auraient raté sans la découverte fortuite d'un développeur attentif à une anomalie de performance.

Les outils pour réduire le risque

Aucun outil ne garantit une protection totale, mais plusieurs couches de défense réduisent significativement la surface d'exposition.

  • Socket analyse le comportement déclaré du package avant installation : accès réseau, fichiers système, variables d'environnement. Un package qui fait des requêtes sortantes au moment de l'install est immédiatement signalé.
  • Snyk et Dependabot surveillent les dépendances en continu et ouvrent automatiquement des pull requests pour les mises à jour de sécurité.
  • OSSF Scorecard attribue un score de sécurité à chaque projet open source en vérifiant des critères concrets : revue de code obligatoire, protection de branches, signature des releases, MFA des mainteneurs.
  • Le lockfile (package-lock.json, yarn.lock, pnpm-lock.yaml) garantit que vous installez exactement les mêmes versions en dev, en CI et en prod. Un lockfile non commité est une invitation à l'attaque par confusion de dépendances.

Les pratiques à adopter dès maintenant

  • Auditer les permissions de ses scripts npm : interdire les scripts postinstall des dépendances tierces avec npm config set ignore-scripts true dans les environnements sensibles.
  • Vérifier les statistiques d'un package avant de l'installer : date de création, mainteneurs, historique des versions. Un package créé il y a 3 jours avec 1 mainteneur mérite plus de méfiance.
  • Générer et vérifier un SBOM (Software Bill of Materials) pour avoir une liste exhaustive des dépendances transitives incluses dans une application.
  • Isoler les builds CI/CD : bloquer l'accès réseau sortant pendant l'installation des dépendances, ou utiliser un miroir privé vérifié.

La supply chain est devenue le vecteur d'attaque privilégié des acteurs sophistiqués, étatiques ou non, parce qu'elle offre un levier de multiplication unique : compromettre un seul package peut toucher des dizaines de milliers de projets. La bonne nouvelle, c'est que des outils concrets existent, et que quelques pratiques de base réduisent considérablement l'exposition sans ralentir le développement.

Cet article a été partiellement rédigé ou modifié à l'aide d'une intelligence artificielle.