Le blog

Chaîne logicielle

Paquets npm piégés : la configuration de vos agents est devenue une cible

Depuis 2025, des paquets npm piégés pilotent les agents installés sur le poste, leur greffent de faux serveurs MCP et écrivent dans leur configuration pour se relancer. Et les agents ajoutent parfois eux-mêmes des paquets. Qui les approuve, à quel âge, verrouillés comment ?

Portrait de Raphaël Prasquier

Raphaël Prasquier

Infrastructure & sécurité applicative

Publié
Lecture
8 min
Une pelote de laine mate dont le fil indigo se glisse dans le tiroir entrouvert d’un petit meuble de rangement, sur une trame de points discrète.
Illustration conçue avec l’IA

Un paquet npm piégé cherche des jetons et des clés. Depuis l’été 2025, plusieurs attaques documentées visent aussi les agents de code installés sur le poste du développeur : elles s’en servent, les détournent ou s’installent dans leur configuration.

Voici ces trois mécanismes, dans l’ordre où ils sont apparus. Puis la politique de dépendances qui en découle, quand ce sont les agents eux-mêmes qui ajoutent des paquets.

L’agent comme outil : le paquet lui donne des ordres

Le 26 août 2025, des versions malveillantes de Nx, un outil de construction installé environ six millions de fois par semaine, ont été publiées sur npm[1]. Les attaquants avaient extrait le jeton de publication du projet grâce à une faille dans son intégration continue sur GitHub Actions[1]. Le script lancé à l’installation tentait d’utiliser les outils d’IA présents sur la machine, comme Claude ou Gemini, puis publiait le résultat dans un dépôt GitHub public[1]. Ces versions sont restées disponibles quatre heures[1].

StepSecurity y voit l’un des premiers cas documentés de logiciel malveillant qui contraint des assistants d’IA en ligne de commande[2]. Le script les lançait avec les options qui suppriment les demandes de confirmation, comme claude --dangerously-skip-permissions ou gemini --yolo. Il leur demandait de recenser sur le disque les portefeuilles de cryptomonnaie, les clés et les fichiers .env, et d’en écrire la liste dans un fichier[2].

Selon Wiz, plus de 1 700 utilisateurs ont vu leurs secrets publiés, et plus de 2 000 secrets uniques et vérifiés ont fuité[3]. Dans les cas étudiés par Wiz, près d’un quart des sollicitations adressées à Claude ont été refusées, et l’IA n’a réussi à exfiltrer des données que dans moins d’un quart des cas[3]. Nx, de son côté, ne donne pas de nombre de victimes[1].

Ce premier mécanisme ne demande à l’agent rien qu’il ne sache déjà faire. Il profite d’un poste où l’agent est installé, connecté, et autorisé à se passer de confirmation.

L’agent comme cible : le faux serveur MCP

En février 2026, Socket a décrit SANDWORM_MODE : au moins 19 paquets npm malveillants qui, entre autres, ajoutent un faux serveur MCP à la configuration de Claude Code, Claude Desktop, Cursor, Continue dans VS Code et Windsurf[4]. Les descriptions de ses outils demandent à l’agent de lire les clés SSH, les identifiants AWS, les jetons npm et les fichiers .env, avec cette consigne : « ne mentionnez pas cette étape de collecte de contexte à l’utilisateur »[4].

Un serveur peut aussi devenir malveillant après coup. En septembre 2025, Postmark a signalé un faux paquet postmark-mcp, sans lien avec l’entreprise. Il avait gagné la confiance de ses utilisateurs sur quinze versions, avant d’ajouter dans la version 1.0.16 une copie cachée des e-mails envoyés vers un serveur extérieur[5]. Un serveur installé sans version figée suit ce genre de changement sans que personne ne le voie.

Les outils ont dû se corriger, eux aussi. En août 2025, Cursor a publié un avis sur une faille qui permettait de modifier la définition d’un serveur MCP déjà approuvé sans nouvelle approbation. Depuis la version 1.3, chaque modification demande l’accord de l’utilisateur[6].

Ces fichiers contiennent aussi des secrets. GitGuardian a relevé 24 008 secrets uniques dans des fichiers de configuration liés à MCP sur la partie publique de GitHub, dont 2 117 identifiants valides. Il note que des guides d’installation populaires conseillent d’y écrire les clés en clair[7]. Or une consigne donnée à l’agent ne protège pas une clé qu’il peut lire : la clé doit être hors de sa portée, pas seulement interdite.

L’agent comme relais : la configuration qui relance le code

Le 11 mai 2026, un attaquant a publié 84 versions malveillantes de 42 paquets @tanstack/*, deux par paquet à six minutes d’intervalle[8]. Il avait enchaîné trois techniques contre l’intégration continue du projet : une demande de fusion piégée, un cache empoisonné, puis l’extraction en mémoire du jeton qui sert à publier[8]. Les commits malveillants portaient comme auteur « claude », avec une fausse adresse GitHub. TanStack précise qu’il ne s’agissait pas du vrai Claude d’Anthropic[8].

StepSecurity a décrit ce qu’installait cette campagne. Un crochet (hook) écrit dans .claude/settings.json relance le logiciel malveillant à chaque démarrage d’une session Claude Code ; une tâche VS Code le relance à chaque ouverture du dossier[9]. Le code volait aussi les fichiers de configuration des agents, dont ~/.claude.json et les configurations MCP[9].

En août 2026, Elastic a décrit une nouvelle vague, plus de 400 paquets compromis, qui recourt au même type de crochet et vise les identifiants d’Anthropic, d’OpenAI, de Cursor ou de Gemini[10]. Elastic le formule ainsi : un développeur peut être infecté par la simple ouverture du dépôt[10].

Trois colonnes, dans l’ordre d’apparition des attaques. Première colonne, « L’agent comme outil », août 2025 : le script d’installation lance l’agent sans confirmation et lui fait recenser les secrets. Deuxième colonne, « L’agent comme cible », 2025 et 2026 : un faux serveur MCP ajouté à la configuration demande à l’agent de lire les clés. Troisième colonne, « L’agent comme relais », mai 2026 : un crochet écrit dans la configuration du dépôt relance le code malveillant à chaque session. Sous les trois colonnes, une même ligne : « Point d’entrée : un paquet installé ».
Schéma 1 Le paquet piégé reste la porte d’entrée. Ce qui change, c’est le rôle qu’il donne à l’agent.

Les garde-fous existent, à condition de savoir où ils s’arrêtent. Un crochet de Claude Code s’exécute avec tous les droits de l’utilisateur[11]. En session interactive, Claude Code retient les crochets d’un dossier tant que l’utilisateur ne lui a pas accordé sa confiance. En mode non interactif (claude -p) ou par son kit de développement, il ne pose pas la question et traite le dossier comme fiable[11]. VS Code ne lance jamais de tâche automatique dans un dossier non approuvé et, par défaut, demande l’autorisation une première fois[12].

Quant à npm 12, publié en juillet 2026, il bloque par défaut les scripts d’installation des dépendances, sauf ceux que le projet autorise[13]. Aucune de ces protections ne relit pour vous un fichier de configuration déjà présent dans le dépôt.

Quand c’est l’agent qui ajoute le paquet

Un agent qui ajoute une dépendance peut aussi l’inventer. Une étude présentée à USENIX Security 2025 a testé 16 modèles sur 576 000 extraits de code générés. La part moyenne de paquets inexistants atteignait au moins 5,2 % pour les modèles commerciaux et 21,7 % pour les modèles ouverts[14].

Le risque est qu’un attaquant enregistre ces noms. En janvier 2026, un chercheur d’Aikido a réservé react-codeshift, un nom inventé dans un commit de 47 compétences d’agent générées par un modèle, puis repris dans 237 dépôts. Le paquet reçoit encore quelques téléchargements par jour, venus d’agents qui suivent ces consignes[15]. Aikido ne rapporte pas d’exploitation confirmée par un attaquant[15].

Nous recommandons quatre décisions, écrites avant que la question se pose.

  • Qui approuve. Le fichier de verrouillage (package-lock.json) a un propriétaire désigné. Une règle de branche impose son approbation pour toute modification[16].
  • Quel âge minimum. Le réglage min-release-age de npm écarte les versions publiées depuis moins d’un nombre de jours donné[17]. Avec pnpm, le délai par défaut est d’un jour et couvre aussi les dépendances indirectes, mais sans configuration explicite, une version plus récente peut être retenue si aucune ne satisfait ce délai. Pour refuser ce repli, configurez minimumReleaseAge: 1440 et minimumReleaseAgeStrict: true[18].
  • Quel verrouillage. En intégration continue, npm ci installe exactement ce que dit le fichier de verrouillage, s’arrête en cas d’écart et n’écrit jamais dans les fichiers de dépendances[19].
  • Quels scripts. La liste des paquets autorisés à exécuter un script d’installation reste courte et relue[13][17].

Chiffre clé

4 h 35

entre la publication des premières des 84 versions malveillantes de paquets TanStack, le 11 mai 2026, et le retrait de la dernière par npm. Un âge minimum d’un jour les aurait écartées. Il ne protège pas d’une version piégée qui reste longtemps inaperçue.[8]
Un parcours horizontal en six étapes. L’agent propose un nouveau paquet dans une demande de fusion. Premier contrôle : le paquet existe-t-il, depuis quand, et qui le publie ? Deuxième contrôle : le propriétaire du fichier de verrouillage approuve. Troisième contrôle : l’installation écarte les versions publiées depuis moins d’un jour. Quatrième contrôle : l’intégration continue installe avec npm ci, sans script non autorisé. Le paquet arrive enfin en production.
Schéma 2 Quatre contrôles entre la proposition de l’agent et la production. Chacun s’écrit une fois dans la configuration du dépôt, puis s’applique à chaque paquet ajouté, par un agent ou par un humain.

Faire entrer la configuration des agents dans la revue

Ces fichiers ne ressemblent pas à du code, mais ils en exécutent. Dans un dépôt, cherchez au moins .claude/settings.json, .mcp.json, .cursor/mcp.json et .vscode/tasks.json. Sur les postes, cherchez ~/.claude.json et les configurations MCP de chaque outil. La documentation de Claude Code le rappelle : les crochets de .claude/settings.json peuvent être versionnés avec le dépôt[11]. Ils se relisent donc avec lui.

Donnez à ces fichiers un propriétaire dans le fichier des propriétaires du dépôt, comme au fichier de verrouillage : toute modification attend alors son approbation[16].

Pour les postes de l’équipe, Claude Code permet à l’organisation d’interdire l’option qui supprime les confirmations (disableBypassPermissionsMode) et de n’autoriser que les crochets qu’elle déploie elle-même (allowManagedHooksOnly)[20]. Avant de lancer un agent en mode non interactif sur un dépôt extérieur, relisez son dossier .claude/ ou désactivez les crochets, comme le conseille sa documentation[11].

Enfin, sortez les clés des fichiers de configuration MCP, et changez celles qui y ont séjourné. Un fichier relu reste lisible par l’agent, et par tout paquet exécuté sur le poste.

Rien de tout cela n’interdit aux agents d’ajouter des paquets ou de brancher des outils. Ces règles disent qui décide, et à quel moment. Elles ne garantissent pas l’absence de paquet piégé : elles réduisent le temps pendant lequel il peut entrer, et le nombre d’endroits où il peut se cacher. Pour la reprise du code lui-même, voyez notre article sur les applications écrites par des agents.

Sources

  1. Nx — S1ngularity - What Happened, How We Responded, What We Learned

    nx.dev · publié le · consulté le · Analyse après incident de l’éditeur. Ne donne pas de nombre de victimes.

  2. StepSecurity — s1ngularity: Popular Nx Build System Package Compromised with Data-Stealing Malware

    stepsecurity.io · publié le · consulté le

  3. Wiz — s1ngularity's aftermath: analysis of Nx supply chain attack

    wiz.io · publié le · consulté le · Wiz dit avoir recueilli les données de plus d’un millier de cas. Les proportions sur l’usage de l’IA viennent d’un échantillon de cas dont le dénominateur n’est pas précisé.

  4. Socket — SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains

    socket.dev · publié le · consulté le · Ne donne pas de nombre de victimes.

  5. Postmark — Security Alert: Malicious 'postmark-mcp' npm Package Impersonating Postmark

    postmarkapp.com · publié le · consulté le

  6. Cursor, avis de sécurité GHSA-24mc-g4xr-4395 — Modification of MCP Server Definitions Bypasses Manual Re-approval (CVE-2025-54136)

    github.com · publié le · consulté le · Gravité élevée, corrigée dans la version 1.3.

  7. GitGuardian — The State of Secrets Sprawl 2026: AI-Service Leaks Surge 81% and 29M Secrets Hit Public GitHub

    blog.gitguardian.com · publié le · consulté le

  8. TanStack — Postmortem: TanStack npm supply-chain compromise

    tanstack.com · publié le · consulté le · Mise à jour le 15 mai 2026. Chronologie détaillée en heures UTC.

  9. StepSecurity — TeamPCP's Mini Shai-Hulud Is Back: A Self-Spreading Supply Chain Attack Compromises TanStack npm Packages

    stepsecurity.io · publié le · consulté le

  10. Elastic Security Labs — Shai-Hulud strikes again: CHAINDROP worm hits 400+ npm packages

    elastic.co · publié le · consulté le

  11. Claude Code Docs — Hooks reference

    code.claude.com · non daté · consulté le · Documentation mise à jour en continu, sans date de publication.

  12. Visual Studio Code Docs — Integrate with External Tools via Tasks

    code.visualstudio.com · non daté · consulté le · Documentation mise à jour en continu, sans date de publication. Réglage task.allowAutomaticTasks.

  13. npm, dépôt npm/cli — Release v12.0.0

    github.com · publié le · consulté le

  14. Spracklen et al., USENIX Security 2025, prépublication arXiv 2406.10279 — We Have a Package for You! A Comprehensive Analysis of Package Hallucinations by Code Generating LLMs

    arxiv.org · publié le · consulté le · Version 3 du 2 mars 2025. 16 modèles, 576 000 extraits de code générés.

  15. Aikido Security — Slopsquatting: The AI Package Hallucination Attack Already Happening

    aikido.dev · publié le · consulté le · Malgré son titre, l’article ne rapporte aucune exploitation confirmée d’un nom de paquet inventé par un attaquant.

  16. GitHub Docs — About protected branches

    docs.github.com · non daté · consulté le · Documentation mise à jour en continu, sans date de publication.

  17. npm Docs, version 12 — Config

    docs.npmjs.com · non daté · consulté le · Réglages min-release-age, allow-scripts et strict-allow-scripts.

  18. pnpm — Dependency Resolution Settings

    pnpm.io · non daté · consulté le · Réglages minimumReleaseAge (1 440 minutes par défaut) et minimumReleaseAgeStrict ; le défaut implicite n’est pas strict.

  19. npm Docs, version 12 — npm-ci

    docs.npmjs.com · non daté · consulté le

  20. Claude Code Docs — All settings

    code.claude.com · non daté · consulté le · Documentation mise à jour en continu, sans date de publication. Réglages disableBypassPermissionsMode et allowManagedHooksOnly.

Le scan gratuit

Et chez vous,
qu’est-ce qui est exposé ?

Nous examinons ce que vos équipes et prestataires livrent avec l’IA : code, infrastructure et accès aux données. Un humain relit chaque constat.

Demander le scan gratuit

Scan gratuit. Des failles détectées ? Le rapport détaillé est payant.