EN FR ES PT DE AR 中文

Les agents de codage IA ont supprimé le dernier auditeur humain. Votre chaîne d'approvisionnement logicielle est désormais sans filet.

La génération de code agentique a discrètement transféré la vérification des dépendances des ingénieurs vers des machines qui ne vérifient rien du tout. La solution n'est pas de fuir un langage ou un registre. C'est de mettre en cage ce que vos agents exécutent.

Demandez à un ingénieur quels paquets ont été livrés dans la fonctionnalité de la semaine dernière, et il y a peu vous obteniez une réponse. Demandez-le maintenant, quand un agent a écrit le code, et vous récoltez souvent un haussement d'épaules. L'agent a ajouté la dépendance. Le gestionnaire de paquets a tiré les siennes. Personne n'a rien relu, parce que la relecture n'a jamais fait partie du flux de travail que l'outil vendait. C'est là, précisément, que se loge le vrai sujet de sécurité de la chaîne d'approvisionnement des agents de codage IA.

Encore faut-il être précis sur ce que recouvre « c'est l'agent qui l'a fait », car trois mécanismes distincts se cachent derrière cette phrase. L'outil piloté par un modèle décide qu'une bibliothèque est nécessaire et écrit l'import. Votre gestionnaire de paquets étend ensuite ce seul nom en un arbre de dépendances transitives que vous n'avez jamais choisies. L'extension de l'éditeur lance l'installation, et souvent les tests, directement dans votre environnement de développement, en simple effet de bord de « juste essayer ». Un humain qui choisit une bibliothèque jette au moins un œil au dépôt, au nombre de téléchargements, au dernier commit. Le résolveur, lui, ne regarde rien, et l'extension exécute ce que le résolveur a produit. Les paquets situés trois niveaux plus bas reçoivent exactement l'attention que cette chaîne leur accorde, c'est-à-dire aucune.

Tous les agents ne se comportent pas ainsi, et la nuance compte. Beaucoup s'arrêtent encore avant chaque commande shell pour demander confirmation, et les éditeurs documentent ces contrôles d'approbation : l'agent de Cursor dispose d'un mode d'exécution automatique qui lance sans confirmation les commandes inscrites sur une liste blanche, et Claude Code d'Anthropic propose un mode d'acceptation automatique ainsi que des listes de permissions, en plus de ses invites par défaut. Le fait documenté, c'est que ces modes sans permission existent et que ce sont précisément ceux qu'on vend pour la vitesse. À quelle fréquence les équipes les laissent activés, aucun éditeur ne le publie : traitez donc l'idée que la relecture humaine tombe à zéro comme un raisonnement, pas comme une mesure. Elle découle du fonctionnement de ces modes, pas d'une enquête de terrain. En France comme ailleurs, le RGPD et le futur cadre de l'AI Act imposent une traçabilité des systèmes, mais aucun texte n'oblige un agent de codage à faire relire ses dépendances avant de les exécuter.

Que se passe-t-il quand le paquet que personne n'a vérifié est malveillant ?

Vous obtenez un scénario déjà survenu, et dont la fréquence grimpe. Le rapport State of the Software Supply Chain 2024 de Sonatype a recensé plus de 512 000 paquets open source malveillants sur une seule année, soit une hausse de 156 % par rapport à l'année précédente. C'est un décompte, pas une probabilité mesurée, mais la tendance ne fait aucun doute : plus les registres hébergent de paquets hostiles, plus une résolution donnée a de chances d'en croiser un, même si personne ne peut avancer de chiffre ferme sur la probabilité exacte. Où un tel paquet se cacherait-il ? Les travaux d'Endor Labs sur la gestion des dépendances montrent qu'environ 95 % des dépendances vulnérables sont transitives, c'est-à-dire indirectes, jamais choisies à la main par un développeur. Il s'agit de dépendances vulnérables, pas malveillantes : le chiffre mesure où logent les failles, pas où frappent les attaques. Mais les deux partagent la même cachette : si les failles accidentelles se concentrent déjà dans les couches qu'un agent résout en silence, c'est exactement là que du code planté resterait, lui aussi, non lu.

L'incident documenté rend la chose concrète. Les chercheurs en sécurité de Snyk ont décrit le cas d'un développeur testant une intégration de l'éditeur Cursor, qui a récupéré une copie empoisonnée d'un paquet Python très utilisé, en tant que dépendance transitive. Le code malveillant écrivait un fichier de démarrage caché qui s'exécutait à l'import. Ce qui a trahi l'attaque relève presque du comique : la charge malveillante engendrait des sous-processus Python de façon récursive jusqu'à épuiser la mémoire et faire planter la machine. La détection tient de l'accident lié à l'épuisement des ressources, pas d'un contrôle qui se serait déclenché.

Suivez le mécanisme, et la conclusion dérange. Personne n'a eu besoin d'être négligent. Le comportement ordinaire de la chaîne d'outils a suffi : l'agent a demandé un paquet, le résolveur a ajouté ce dont ce paquet dépendait, l'intégration l'a exécuté. Aucune personne n'a choisi le code malveillant. Trois étapes automatisées ont géré le tout de bout en bout, et aucune ne procède à un audit.

Fuir le registre est le mauvais réflexe

Après un incident de ce genre, le réflexe naturel consiste à se méfier de l'écosystème : accuser le dépôt, se replier sur un langage à la réputation plus « sûre ». C'est se tromper de cible. L'exposition n'a jamais logé dans la marque d'un registre. Elle se trouve dans du code non audité, plusieurs dépendances plus bas, et tous les écosystèmes publics en portent. Les décomptes de paquets malveillants de Sonatype couvrent npm, PyPI et le reste : changer de registre, c'est simplement changer de marque à laquelle on ne fait plus confiance, tandis que le code non lu reste sur votre serveur de build.

Comment met-on réellement un agent de codage en cage ?

Trois contrôles font l'essentiel du travail, et aucun n'est exotique ou hypothétique. Chacun vise la même cible : cesser de trancher si un paquet est digne de confiance, et contraindre ce qu'un paquet non fiable peut faire.

D'abord, un blocage par défaut des flux sortants sur le build. Un agent de build a besoin d'un index de paquets et, parfois, d'un hébergeur git. Il n'a besoin ni de votre point de terminaison de métadonnées cloud, ni de votre réseau interne, ni d'un serveur arbitraire à l'étranger. Sur GitHub Actions, ce contrôle est déjà déployable aujourd'hui via Harden-Runner de StepSecurity, qui bloque le trafic sortant par défaut et accepte une liste blanche :

# .github/workflows : bloquer les flux sortants, autoriser seulement l'essentiel
- uses: step-security/harden-runner@v2
  with:
    egress-policy: block
    allowed-endpoints: >
      pypi.org:443
      files.pythonhosted.org:443
      github.com:443

Une charge malveillante qui tente d'exfiltrer une clé SSH n'a désormais nulle part où l'envoyer, et Harden-Runner consigne l'appel bloqué, si bien que la tentative remonte dans le journal d'exécution. Vous avez contraint ce que le paquet peut faire, sans avoir eu à statuer sur sa fiabilité.

Ensuite, installez depuis un fichier de verrouillage versionné, à empreintes cryptographiques, et refusez tout ce qui ne correspond pas. Épingler une version de premier niveau ne suffit pas, car le danger loge dans l'arbre transitif. Un fichier de verrouillage enregistre chaque paquet résolu et son empreinte, si bien qu'une version substituée ou empoisonnée ne peut plus arriver en silence. Les commandes existent déjà : npm ci installe strictement depuis un package-lock.json versionné, pip install --require-hashes -r requirements.txt refuse tout téléchargement dont l'empreinte est absente ou erronée, et ajouter --ignore-scripts sur npm bloque l'exécution de code à l'installation dont dépendent de nombreuses attaques. Les empreintes une fois épinglées, une copie corrompue cesse d'être une récupération silencieuse et devient un diff qu'un humain, ou un scanner, relit avant toute exécution :

# package-lock.json, visible dans la pull request
   "node_modules/log-helper": {
-    "version": "2.4.0",
-    "integrity": "sha512-6b1e2c..."
+    "version": "2.4.1",
+    "integrity": "sha512-00d4af..."

Sans le fichier de verrouillage, le résolveur récupère simplement la nouvelle version et le changement reste invisible. Avec lui, la mutation devient une ligne rouge qui attend une relecture, plutôt qu'une installation silencieuse.

Enfin, scannez automatiquement chaque changement de dépendance, et faites échouer le build lorsqu'il découvre quelque chose qu'il ne peut pas justifier. C'est là que l'outillage a rattrapé son retard. OSV-Scanner confronte les fichiers de verrouillage à une base de vulnérabilités publique, et des services comme Socket inspectent chaque paquet ajouté à la recherche de scripts d'installation, de code obfusqué et d'accès réseau inattendus, directement sur la pull request. Reliez cet outil au même environnement isolé et exécutez-le à chaque modification du fichier de verrouillage :

# .github/workflows : faire échouer la PR sur une dépendance connue comme malveillante ou nouvellement ajoutée
- uses: google/osv-scanner-action@v2
  with:
    scan-args: "--lockfile=package-lock.json"

Superposer un modèle par-dessus, c'est selon moi le moment où l'économie du problème bascule enfin en faveur du défenseur, mais cette partie relève du raisonnement, pas d'un test chiffré : les mêmes modèles qui installent sans lire savent aussi lire un diff de dépendance plus vite qu'une personne, repérer un crochet de démarrage suspect, et retracer un chemin d'exfiltration. Utilisés ainsi, l'attaquant automatise l'attaque et vous automatisez l'auditeur. Les scanners décrits plus haut forment le socle déployable ; le modèle n'est qu'un accélérateur par-dessus, pas un substitut à l'environnement isolé et au fichier de verrouillage.

Nous appliquons la même discipline dans chaque mission de conseil, et elle irrigue aussi l'ensemble des analyses que nous publions : garder l'humain dans la boucle là où le jugement compte, et clôturer la machine là où il ne compte pas.

Les agents ne retourneront pas dans leur boîte, et ce n'est pas souhaitable. Mais une équipe qui installe ce qu'elle ne lit jamais a automatisé la disparition de sa propre dernière ligne de défense. La réponse ne consiste pas à faire davantage confiance aux paquets. Elle consiste à donner au build un endroit sûr où s'exécuter, un fichier de verrouillage qui rend toute altération visible, et un scanner qui lit chaque changement pour qu'aucune dépendance n'atteigne la production sans avoir été lue.

Questions fréquentes

Les agents de codage IA sont-ils plus dangereux qu'un développeur humain qui installe des paquets ?

Il s'agit de la même catégorie d'attaque de la chaîne d'approvisionnement, mais l'exposition est plus large dans les modes d'auto-approbation et d'installation en tâche de fond que les équipes activent pour gagner en vitesse : l'agent résout et exécute des dépendances transitives sous un regard humain quasi inexistant, si bien qu'une compromission peut se propager avant que quiconque ne s'en aperçoive.

Faut-il changer de langage de programmation après une compromission de dépendance ?

Non. Tout écosystème public porte du code transitif non audité, et les travaux d'Endor Labs situent environ 95 % des dépendances vulnérables dans cette couche transitive : changer de langage revient à déplacer la marque à laquelle on ne fait plus confiance, sans rien résoudre. Épinglez les versions via un fichier de verrouillage à empreintes, vérifiez la provenance, et isolez l'exécution plutôt.

Un agent IA peut-il aider à se défendre contre les paquets malveillants plutôt que d'en être seulement la cause ?

Oui, et le socle déployable n'a rien d'exotique : faites tourner les builds dans un environnement isolé à blocage par défaut comme Harden-Runner, et placez un scanner automatisé comme OSV-Scanner ou Socket sur chaque diff de dépendance pour signaler scripts d'installation, obfuscation et appels réseau inattendus. Un modèle peut trier les diffs signalés plus vite qu'une personne, mais traitez cela comme un accélérateur par-dessus le scanner et l'environnement isolé, pas comme leur remplacement.

À lire aussi

Rédigé par un persona éditorial IA du système éditorial propriétaire d'Abyshire et relu par notre équipe.