Joe Desimone

Comment nous avons détecté l'attaque de la chaîne d'approvisionnement d'Axios

Joe Desimone raconte comment il a réussi à déjouer l'attaque de la chaîne d'approvisionnement d'Axios grâce à un outil de démonstration construit en une après-midi.

9 minutes de lectureDetection Engineering, Enablement
Comment nous avons détecté l'attaque de la chaîne d'approvisionnement d'Axios

Préambule

Lundi dernier, alors que je travaillais tard, j'ai reçu une alerte Slack provenant d'un outil de surveillance que j'avais créé trois jours plus tôt. Axios compromis ; l'un des paquets npm les plus populaires au monde.

Mon cœur s'est mis à battre la chamade, je savais que chaque seconde comptait pour réagir et limiter les dégâts. Mais honnêtement, c'était tellement fou que j'ai pensé qu'il devait s'agir d'un faux positif. J'ai tout vérifié et revérifié à plusieurs reprises, même si cela semblait manifestement malveillant.

Ce n'était pas un faux positif. Il s'agit de l'une des plus importantes compromissions de la chaîne d'approvisionnement jamais réalisées sur npm, qui serait attribuée à des acteurs de la République populaire démocratique de Corée (RPDC). Nous l'avons attrapé grâce à une preuve de concept que j'ai élaborée un vendredi après-midi, qui fonctionnait sur mon ordinateur portable et qui était alimentée par une IA lisant les différences.

Je veux partager toute l'histoire. Comment nous en sommes arrivés là, ce que j'ai construit et pourquoi je pense que le fait de le partager ouvertement rend tout le monde un peu plus sûr.

La chaîne d'approvisionnement me préoccupe depuis un certain temps.

Certains incidents récents liés à la chaîne d'approvisionnement m'ont véritablement empêché de dormir. La compromission de la chaîne d'approvisionnement est un problème difficile. Chez Elastic, nous avons beaucoup de développeurs et nos clients nous font confiance pour les protéger. Il est clair que le statu quo n'est pas respecté et que nous avons besoin de nouvelles technologies ou procédures pour nous aider. J'avais quelques idées concernant un écosystème plus fiable, validé par l'IA, qui s'appuierait sur les principes de contrôle des applications tout en limitant les coûts et les frictions.

Mais c'est surtout le compromis de Trivy qui m'a interpellé. Le 19 mars, un groupe appelé TeamPCP a compromis l'action GitHub aquasecurity/trivy-action (celle du populaire scanner de sécurité Trivy, oui, un outil de sécurité). Ils ont injecté un voleur d'informations d'identification qui a recueilli les secrets des pipelines CI/CD. Un grand nombre d'informations d'identification ont été volées.

Cela s'est rapidement répercuté. Le 24 mars, LiteLLM a été touché. TeamPCP a volé les identifiants de publication PyPI de LiteLLM à travers le pipeline Trivy empoisonné, et les a utilisés pour pousser des versions malveillantes qui étaient des voleurs d'identifiants agressifs. Clés SSH, références cloud, clés API, données de portefeuille, tout.

LiteLLM est un paquetage que j'ai moi-même utilisé. On peut donc dire qu'à ce moment-là, j'étais complètement "la nuit."

Je savais qu'avec toutes les informations d'identification divulguées à la suite de la faille de Trivy, il y en aurait certainement d'autres. Nous devions faire quelque chose pour garder une longueur d'avance. Tant pour nos clients que pour protéger Elastic.

Vendredi, après le vol de nuit

Je venais de rentrer en avion du RSAC 2026 à San Francisco. Vol de nuit jeudi soir. Si vous avez déjà fait un aller-retour après quatre jours de conférence, vous savez dans quel état j'étais. Cependant, j'étais plus excité que jamais par un nouveau projet, alors je me suis assis et j'ai mis au point la version 0.0.1.

L'idée : surveiller les changements au fur et à mesure qu'ils sont poussés vers les dépôts de paquets. Exécutez un diff pour voir ce qui a changé. Utilisez AI/LLM pour déterminer si les changements sont malveillants. C'est à peu près tout.

Le pipeline se présente comme suit :

  1. Interrogez l'API changelog de PyPI et le flux CouchDB _changes de npm pour connaître les nouvelles versions.
  2. Filtre sur une liste de surveillance des 15 000 premiers paquets par nombre de téléchargements
  3. Téléchargez l'ancienne et la nouvelle version directement depuis le registre (pas d'installation de pip, pas d'installation de npm, pas d'exécution de code).
  4. Diffusez-les dans un rapport markdown
  5. Envoyez la différence à un LLM : "est-ce malveillant ?"
  6. Si oui, alertez Slack

Je voulais me concentrer principalement sur les paquets supérieurs, car c'est là que les attaquants iraient de toute façon, et ce serait beaucoup moins coûteux en termes de jetons et de calcul. Il était tout à fait possible de l'exécuter sur mon ordinateur portable.

Pourquoi un curseur ?

Il existe de nombreux harnais pour les agents. J'ai écrit les miens pour des projets tels que la rétro-ingénierie de logiciels malveillants d'IA. Mais je n'avais pas beaucoup de temps, alors j'ai choisi d'utiliser Cursor car c'est l'un de mes principaux outils de développement. L'interface de programmation de l'agent vous permet de l'invoquer de manière programmatique : transmettez-lui un espace de travail, une instruction et un modèle. Je l'utilise en mode ask (lecture seule) afin qu'il ne puisse que lire le diff, sans jamais rien modifier. L'ensemble de l'étape d'analyse est un seul appel de sous-processus.

L'invitation est simple. Je lui indique ce qu'il doit rechercher (code obfusqué, base64, exec/eval, appels réseau inattendus, stéganographie, mécanismes de persistance, abus de script de cycle de vie) et lui demande de répondre par Verdict: malicious ou Verdict: benign. Analysez le verdict, agissez en conséquence.

Sur la sélection des modèles

J'utilise normalement Opus 4.6 ou GPT 5.4 pour la plupart des choses. Opus, en particulier pour les tâches liées à la cybersécurité. Mais je voulais limiter les coûts pour un outil qui doit analyser des dizaines de publications par heure.

L'équipe de Cursor a publié récemment de très bons articles de blog, l'un sur la recherche rapide d'expressions rationnelles pour les outils d'agent et un autre sur leur approche RL en temps réel, où ils utilisent des jetons d'inférence de production réels comme signaux d'entraînement et déploient des points de contrôle améliorés environ toutes les cinq heures. Une ingénierie vraiment impressionnante.

J'ai donc voulu donner un coup de pouce à Composer 2 . J'ai utilisé le mode rapide, qui est vraiment rapide. Parfait pour une utilisation en temps réel. Peu coûteux, rapide et efficace (d'après mes tests).

Tests sur Telnyx

Vous devez tester ces choses pour vous assurer qu'elles fonctionneront réellement. En général, cela signifie qu'il faut modifier les messages-guides à plusieurs reprises.

J'ai eu de la chance (ou de la malchance) avec le timing. Le vendredi même où je construisais ceci, le paquet PyPI telnyx a été compromis par TeamPCP. Ils ont injecté 74 lignes de code malveillant dans _client.py: charges utiles cachées dans des fichiers audio WAV (stéganographie), obfuscation base64, implant de persistance Windows déguisé en msbuild.exe, et exfiltration vers un C2 codé en dur.

J'ai utilisé la différence entre le paquet légitime et le paquet malveillant telnyx pour construire l'invite initiale. Le modèle a été très efficace pour identifier les changements malveillants de ce type. Je voulais également savoir immédiatement si une compromission avait été détectée, et j'ai donc ajouté l'alerte Slack.

Lundi soir

Je l'ai laissé fonctionner pendant le week-end. Il a passé en revue les publications, tout revenant à l'état normal.

Je n'ai jamais obtenu un seul faux positif, ce qui est franchement étrange si vous avez déjà fait du travail de détection dans le domaine de la cybersécurité. Nous sommes généralement noyés dans les PF. J'ai intentionnellement demandé au LLM de n'alerter que sur "les compromissions de la chaîne d'approvisionnement" avec un niveau de confiance élevé, car ils ont généralement la gâchette facile dès le départ. Toujours en train d'attraper le cas de test Telnyx, sans aucun PF. Il pourrait s'agir d'un surajustement avec une taille d'échantillon aussi faible, mais nous n'avons pas eu le temps de construire quelque chose de plus robuste.

Lundi soir, alors que je travaillais tard, j'ai reçu une alerte sur Slack.

🚨 Supply Chain Alert: axios 0.30.4
Verdict: MALICIOUS
npm: https://www.npmjs.com/package/axios/v/0.30.4

Vient-elle vraiment de découvrir l'une des plus grandes compromissions de la chaîne d'approvisionnement de mémoire récente ?

J'ai vérifié l'analyse. Je l'ai revérifié. Je l'ai vérifié à nouveau. Les attaquants avaient compromis le compte npm d'un mainteneur, changé l'email en un compte ProtonMail qu'ils contrôlaient, et publié deux versions malveillantes (1.14.1 et 0.30.4). Ils n'ont pas injecté de code directement dans Axios. Au lieu de cela, ils ont ajouté une dépendance fantôme appelée plain-crypto-js qui exécute un crochet post-installation déployant des logiciels malveillants multiplateformes. C'était manifestement malveillant.

La réponse

J'ai immédiatement contacté notre équipe infosec et l'équipe de recherche d'Elastic pour les faire démarrer. Je savais que chaque seconde comptait. Il s'avère que lorsque je les ai contactés, ils avaient déjà reçu des alertes Elastic Defend sur un hôte qui avait installé le paquet malveillant et y répondaient activement. Mais à ce moment-là, personne n'avait pris conscience de l'ampleur du problème et n'avait compris comment la machine avait été infectée. L'outil de suivi a fourni ce contexte manquant.

J'ai essayé d'envoyer un courrier électronique à security@npmjs et j'ai reçu une réponse négative. J'ai essayé de le soumettre à leur portail de sécurité et j'ai obtenu une erreur. J'ai tweeté en désespoir de cause pour obtenir un contact humain. J'ai aussi rapidement ouvert un problème de sécurité sur le repo d'axios lui-même.

Plus tard, j'ai vu un tweet d'un autre chercheur qui avait observé la compromission, et j'ai réalisé que je gérais cela plus comme une vulnérabilité que comme un incident de la chaîne d'approvisionnement. Avec une vulnérabilité, vous vous coordonnez tranquillement. Avec un compromis actif qui installe des logiciels malveillants sur les machines des gens en ce moment même, l'ouverture à tous est la bonne décision. J'ai donc immédiatement communiqué à X tous les détails que j'avais rassemblés.

Nous avons même commencé à recevoir des alertes de notre télémétrie indiquant les organisations touchées dans la nature. L'appareil fonctionnait activement.

Heureusement, l'équipe d'Axios a réagi et a rapidement retiré les paquets. En outre, le serveur C2 de l'attaquant recevait tellement de demandes qu'il tombait en panne. Cela aurait pu être bien pire.

Notre équipe d'Elastic Security Labs a publié des articles techniques complets sur la compromission. La première couvre la chaîne d'attaque de bout en bout, les logiciels malveillants multiplateformes et le protocole C2 : Inside the Axios supply chain compromise - one RAT to rule them all. La seconde couvre les règles de chasse et de détection pour Linux, Windows et macOS : Elastic publie des détections pour la compromission de la chaîne d'approvisionnement d'Axios.

Où allons-nous maintenant ?

La situation actuelle n'est pas brillante et nous devons faire mieux en tant qu'écosystème logiciel, sans parler de l'industrie de la sécurité.

Dans deux semaines en mars :

  • Trivy (un scanner de sécurité) a été compromis pour voler des secrets de CI/CD
  • LiteLLM a été compromis en utilisant ces secrets volés
  • Telnyx a été compromise dans le cadre de la même campagne
  • Axios, l'un des paquets les plus dépendants de npm, a été compromis par un acteur présumé de la RPDC.
  • Et bien plus encore

Les registres de colis sont des infrastructures essentielles. Les équipes qui gèrent PyPI et npm font un excellent travail, mais la menace a dépassé ce que les modèles de confiance actuels peuvent gérer. Nous avons besoin d'une meilleure surveillance automatisée des changements de paquets. Il ne s'agit pas seulement de scanner les signatures, mais de comprendre ce que fait le code. Les LLM sont vraiment bons dans ce domaine, comme le montre ce projet. Et nous devons accélérer la rotation des informations d'identification après les brèches. La cascade Trivy-Litellm-Telnyx s'est produite parce que les créances volées n'ont pas été transférées assez rapidement.

Une chose pratique que vous pouvez faire dès maintenant : n'utilisez pas immédiatement les mises à jour des paquets. Ajoutez un temps de trempage. Laissez les nouvelles versions en attente pendant un certain temps avant que vos constructions ne les prennent en charge. C'est ce que nous faisons avec nos systèmes CI/CD chez Elastic en réponse à shai-hulud. Cela n'empêchera pas tout, mais cela donne à la communauté le temps d'attraper les compromis avant qu'ils n'atteignent vos pipelines CI/CD et les machines des développeurs. La bonne nouvelle est que de nombreux gestionnaires de paquets ont ajouté un support natif pour cela. Par exemple, pour imposer un délai de 7 jours :

npm config set min-release-age 7
pnpm config set minimum-release-age 10080
yarn config set npmMinimumReleaseAge 10080
uv --exclude-newer "7 days ago"

Nous sommes en train de mettre en place un système d'approvisionnement ouvert

Nous publions l'outil : supply-chain-monitor

Je veux être franc. Il s'agit d'une preuve de concept. Je l'ai construit en un après-midi sans dormir. Je ne m'attends pas à ce que quelqu'un l'exploite à un niveau de production. Il nécessite un abonnement à Cursor pour l'analyse LLM, il traite les communiqués de manière séquentielle et les listes de surveillance sont statiques.

Mais l'approche fonctionne. La différenciation des versions de paquets en temps réel et l'utilisation de l'IA pour classer les changements ont permis de détecter une attaque de la chaîne d'approvisionnement sur l'un des paquets les plus populaires de npm.

Je partage cette information parce qu'il est préférable que la communauté tire des enseignements de nos expériences. Si quelqu'un reprend cette idée et construit quelque chose de mieux, tant mieux. Si une équipe d'enregistrement des paquets l'intègre dans son pipeline, c'est encore mieux. Si cela permet à quelqu'un d'autre de réaliser des économies importantes la prochaine fois, cela en valait la peine.

Comment ça marche (pour les curieux)

Surveillance : Deux threads interrogent PyPI (via changelog_since_serial() XML-RPC) et npm (via CouchDB _changes feed). Les nouvelles publications correspondant à la liste de surveillance top-N sont mises en file d'attente. L'état persiste sur last_serial.yaml, de sorte qu'il reprend là où il s'est arrêté.

Diffing : Anciennes et nouvelles versions téléchargées directement à partir des API du registre. Pas d'installation de pip/npm, pas d'exécution de code. Extraction des archives, hachage des fichiers, génération d'un rapport unifié en markdown.

Analyse : Le rapport de diff est transmis à l'agent de curseur CLI en mode lecture seule. L'invite lui demande de rechercher des indicateurs de la chaîne d'approvisionnement. Sortie analysée pour le verdict.

Alerte : Le verdict malveillant déclenche un message Slack avec le nom du paquet, le rang, le lien vers le registre et un résumé de l'analyse.

L'IA dans la sécurité, au-delà de ce projet

La sécurité de la chaîne d'approvisionnement est un enjeu majeur, mais nous ne sommes pas impuissants. L'IA nous donne de nouveaux outils pour nous défendre à grande échelle et à la vitesse de la machine. Ce projet est un exemple d'utilisation de l'IA pour résoudre un problème de sécurité, mais nous avons réalisé de nombreux travaux intéressants avec l'IA dans le cadre d'Elastic Security de manière plus générale. Une chose que je voudrais souligner : notre équipe a récemment publié un article sur l'utilisation d'Attack Discovery, de Workflows et d'Agent Builder pour détecter et confirmer automatiquement les attaques de niveau APT. Cela montre la puissance de la plateforme Elastic, qui fournit une sécurité agentive pour améliorer de manière significative l'efficacité de votre SOC à une époque où nous sommes collectivement noyés dans les attaques.


Le projet supply-chain-monitor est disponible sur github.com/elastic/supply-chain-monitor.

Merci à l'équipe d'Elastic Infosec pour la réponse rapide à l'incident, aux mainteneurs d'axios pour le démantèlement rapide, et à la communauté de la sécurité pour l'effort collectif qui a permis de limiter le rayon d'action de l'explosion.

Partager cet article