{"id":502,"date":"2026-02-07T21:25:24","date_gmt":"2026-02-07T20:25:24","guid":{"rendered":"https:\/\/secure-pipelines.com\/?p=502"},"modified":"2026-03-24T12:55:50","modified_gmt":"2026-03-24T11:55:50","slug":"dependency-confusion-artifact-poisoning-attacks-defenses","status":"publish","type":"post","link":"https:\/\/secure-pipelines.com\/fr\/ci-cd-security\/dependency-confusion-artifact-poisoning-attacks-defenses\/","title":{"rendered":"Confusion de D\u00e9pendances et Empoisonnement d&rsquo;Artefacts : Techniques d&rsquo;Attaque et D\u00e9fenses"},"content":{"rendered":"<h2>Introduction<\/h2>\n<p>Les attaques contre la cha\u00eene d&rsquo;approvisionnement logicielle ont connu une augmentation consid\u00e9rable, tant en fr\u00e9quence qu&rsquo;en sophistication, au cours des derni\u00e8res ann\u00e9es. Plut\u00f4t que d&rsquo;attaquer directement les applications, les adversaires ciblent de plus en plus les couches de r\u00e9solution de d\u00e9pendances et de distribution d&rsquo;artefacts qui sous-tendent le d\u00e9veloppement logiciel moderne. Deux des techniques les plus efficaces dans cette cat\u00e9gorie sont la <strong>dependency confusion<\/strong> (confusion de d\u00e9pendances) et l&rsquo;<strong>artifact poisoning<\/strong> (empoisonnement d&rsquo;artefacts).<\/p>\n<p>Ces attaques exploitent une v\u00e9rit\u00e9 fondamentale : les logiciels modernes sont assembl\u00e9s, et non \u00e9crits \u00e0 partir de z\u00e9ro. Une application typique peut int\u00e9grer des centaines, voire des milliers de packages tiers, d&rsquo;images de conteneurs, de templates CI et de plugins de build \u2014 chacun repr\u00e9sentant un maillon d&rsquo;une cha\u00eene de confiance. Lorsqu&rsquo;un seul maillon est compromis, c&rsquo;est toute la cha\u00eene qui s&rsquo;effondre.<\/p>\n<p>Ce qui rend ces attaques particuli\u00e8rement dangereuses, c&rsquo;est que de nombreuses organisations restent vuln\u00e9rables malgr\u00e9 des programmes de s\u00e9curit\u00e9 matures. Les tests de s\u00e9curit\u00e9 applicatifs traditionnels ne d\u00e9tectent pas une d\u00e9pendance malveillante install\u00e9e lors du build. Les firewalls et les WAF sont sans effet lorsque le code de l&rsquo;attaquant s&rsquo;ex\u00e9cute \u00e0 l&rsquo;int\u00e9rieur de votre pipeline CI\/CD avec un acc\u00e8s r\u00e9seau complet et des identifiants de production.<\/p>\n<p>Ce guide fournit un examen approfondi du fonctionnement de la dependency confusion et de l&rsquo;artifact poisoning, explique pourquoi les pipelines CI\/CD sont des cibles privil\u00e9gi\u00e9es et \u2014 surtout \u2014 quelles d\u00e9fenses pratiques vous pouvez mettre en \u0153uvre d\u00e8s aujourd&rsquo;hui.<\/p>\n<h2>La Dependency Confusion expliqu\u00e9e<\/h2>\n<h3>Comment les gestionnaires de packages r\u00e9solvent les noms<\/h3>\n<p>La plupart des gestionnaires de packages modernes \u2014 npm, pip, RubyGems, NuGet, Maven \u2014 suivent un processus de r\u00e9solution qui consulte un ou plusieurs registres lorsqu&rsquo;un package est demand\u00e9. Lorsqu&rsquo;une organisation utilise \u00e0 la fois un <strong>registre priv\u00e9\/interne<\/strong> (pour les packages propri\u00e9taires) et le <strong>registre public<\/strong> (pour les packages open source), le gestionnaire de packages doit d\u00e9cider quel registre a la priorit\u00e9 lorsque les deux contiennent un package portant le m\u00eame nom.<\/p>\n<p>Le comportement par d\u00e9faut varie selon l&rsquo;\u00e9cosyst\u00e8me, mais un sch\u00e9ma courant est pr\u00e9occupant : de nombreux gestionnaires de packages pr\u00e9f\u00e8rent le <strong>num\u00e9ro de version le plus \u00e9lev\u00e9<\/strong>, quel que soit le registre d&rsquo;origine. Ce choix de conception apparemment anodin constitue le fondement de l&rsquo;attaque par dependency confusion.<\/p>\n<h3>La recherche originale : Alex Birsan (2021)<\/h3>\n<p>En f\u00e9vrier 2021, le chercheur en s\u00e9curit\u00e9 Alex Birsan a publi\u00e9 une recherche r\u00e9volutionnaire d\u00e9montrant comment ce comportement de r\u00e9solution pouvait \u00eatre utilis\u00e9 comme arme. En examinant des noms de packages internes ayant fuit\u00e9 publiquement aupr\u00e8s d&rsquo;entreprises comme Apple, Microsoft et Tesla \u2014 trouv\u00e9s dans des fichiers JavaScript, des manifestes de packages et des messages d&rsquo;erreur \u2014 il a enregistr\u00e9 des packages portant des noms identiques sur les registres publics npm, PyPI et RubyGems, avec des num\u00e9ros de version artificiellement gonfl\u00e9s.<\/p>\n<p>Le r\u00e9sultat fut d\u00e9vastateur. Lorsque les syst\u00e8mes de build de ces entreprises r\u00e9solvaient les d\u00e9pendances, les gestionnaires de packages r\u00e9cup\u00e9raient les packages publics de Birsan au lieu des packages internes l\u00e9gitimes. Ses packages de preuve de concept incluaient des callbacks b\u00e9nins qui transmettaient des informations, confirmant l&rsquo;ex\u00e9cution de code \u00e0 l&rsquo;int\u00e9rieur des r\u00e9seaux d&rsquo;entreprise. Birsan a gagn\u00e9 plus de 130 000 $ en primes de bug bounty aupr\u00e8s de plusieurs organisations.<\/p>\n<h3>Les m\u00e9canismes de l&rsquo;attaque<\/h3>\n<p>L&rsquo;attaque par dependency confusion suit une s\u00e9quence simple :<\/p>\n<ol>\n<li><strong>Reconnaissance :<\/strong> L&rsquo;attaquant identifie les noms de packages internes\/priv\u00e9s utilis\u00e9s par l&rsquo;organisation cible. Ceux-ci peuvent \u00eatre trouv\u00e9s dans des fichiers <code>package.json<\/code> ayant fuit\u00e9, des source maps JavaScript, des messages d&rsquo;erreur, des offres d&#8217;emploi ou des d\u00e9p\u00f4ts open source qui r\u00e9f\u00e9rencent des d\u00e9pendances internes.<\/li>\n<li><strong>Enregistrement :<\/strong> L&rsquo;attaquant enregistre un package portant un nom identique sur le registre public correspondant (npm, PyPI, etc.), en lui attribuant un num\u00e9ro de version tr\u00e8s \u00e9lev\u00e9 (par exemple, <code>99.0.0<\/code>).<\/li>\n<li><strong>Charge utile :<\/strong> Le package public contient du code malveillant dans des scripts d&rsquo;installation ou des hooks post-installation \u2014 du code qui s&rsquo;ex\u00e9cute automatiquement lors de l&rsquo;installation du package.<\/li>\n<li><strong>Ex\u00e9cution :<\/strong> Lorsque le syst\u00e8me de build de l&rsquo;organisation cible ex\u00e9cute <code>npm install<\/code>, <code>pip install<\/code> ou une commande \u00e9quivalente, le gestionnaire de packages r\u00e9sout la d\u00e9pendance vers le package public de l&rsquo;attaquant en raison du num\u00e9ro de version plus \u00e9lev\u00e9.<\/li>\n<li><strong>Compromission :<\/strong> Le script d&rsquo;installation malveillant s&rsquo;ex\u00e9cute avec les privil\u00e8ges du processus de build, obtenant g\u00e9n\u00e9ralement l&rsquo;acc\u00e8s aux variables d&rsquo;environnement (y compris les secrets), aux ressources r\u00e9seau et au code source.<\/li>\n<\/ol>\n<h3>\u00c9cosyst\u00e8mes affect\u00e9s<\/h3>\n<p>La dependency confusion ne se limite pas \u00e0 un seul langage ou \u00e9cosyst\u00e8me. Les \u00e9cosyst\u00e8mes suivants sont tous vuln\u00e9rables :<\/p>\n<ul>\n<li><strong>npm (Node.js) :<\/strong> Le comportement par d\u00e9faut peut favoriser les packages publics par rapport aux packages priv\u00e9s lorsque le scoping n&rsquo;est pas utilis\u00e9.<\/li>\n<li><strong>PyPI (Python) :<\/strong> Le flag <code>--extra-index-url<\/code> de pip v\u00e9rifie \u00e0 la fois les index priv\u00e9 et public, en pr\u00e9f\u00e9rant la version la plus \u00e9lev\u00e9e.<\/li>\n<li><strong>RubyGems (Ruby) :<\/strong> Comportement de r\u00e9solution similaire lorsque plusieurs sources sont configur\u00e9es.<\/li>\n<li><strong>NuGet (.NET) :<\/strong> V\u00e9rifie plusieurs flux configur\u00e9s et peut favoriser la galerie publique.<\/li>\n<li><strong>Maven (Java) :<\/strong> R\u00e9sout \u00e0 partir de plusieurs d\u00e9p\u00f4ts ; les attaquants peuvent publier sur Maven Central avec des identifiants group\/artifact correspondants.<\/li>\n<\/ul>\n<h3>Les scripts d&rsquo;installation comme vecteur de charge utile<\/h3>\n<p>La raison pour laquelle la dependency confusion est si dangereuse est que les gestionnaires de packages prennent en charge l&rsquo;<strong>ex\u00e9cution automatique de code lors de l&rsquo;installation<\/strong>. Dans npm, cela se produit via les scripts <code>preinstall<\/code>, <code>install<\/code> et <code>postinstall<\/code> d\u00e9finis dans <code>package.json<\/code>. En Python, <code>setup.py<\/code> peut ex\u00e9cuter du code arbitraire pendant <code>pip install<\/code>. Ces hooks ont \u00e9t\u00e9 con\u00e7us pour des t\u00e2ches de build l\u00e9gitimes, mais fournissent aux attaquants un vecteur d&rsquo;ex\u00e9cution id\u00e9al \u2014 le code s&rsquo;ex\u00e9cute avant m\u00eame que l&rsquo;application ne soit construite, souvent avec des privil\u00e8ges \u00e9lev\u00e9s.<\/p>\n<h2>Artifact Poisoning : au-del\u00e0 des packages<\/h2>\n<p>Alors que la dependency confusion cible sp\u00e9cifiquement les registres de packages, l&rsquo;<strong>artifact poisoning<\/strong> est une cat\u00e9gorie plus large d&rsquo;attaques sur la cha\u00eene d&rsquo;approvisionnement qui peut cibler tout artefact externe consomm\u00e9 durant le cycle de vie du d\u00e9veloppement logiciel. La surface d&rsquo;attaque s&rsquo;\u00e9tend bien au-del\u00e0 des gestionnaires de packages.<\/p>\n<h3>Images de base de conteneurs compromises<\/h3>\n<p>Les images de conteneurs extraites de Docker Hub ou d&rsquo;autres registres publics sont un vecteur d&rsquo;attaque courant. Un attaquant peut publier une image malveillante avec un nom similaire \u00e0 une image de base populaire, ou compromettre une image existante en acc\u00e9dant au compte du mainteneur. Si votre Dockerfile sp\u00e9cifie <code>FROM python:3.11<\/code> en utilisant un tag mutable, une image compromise pouss\u00e9e vers ce tag sera int\u00e9gr\u00e9e dans chaque build ult\u00e9rieur.<\/p>\n<h3>Templates CI\/CD alt\u00e9r\u00e9s<\/h3>\n<p>Les templates GitHub Actions et GitLab CI r\u00e9f\u00e9renc\u00e9s depuis des d\u00e9p\u00f4ts publics repr\u00e9sentent une autre surface d&rsquo;attaque significative. Lorsqu&rsquo;un workflow r\u00e9f\u00e9rence <code>uses: some-org\/some-action@main<\/code>, le code ex\u00e9cut\u00e9 dans votre pipeline est contr\u00f4l\u00e9 par quiconque poss\u00e8de un acc\u00e8s en \u00e9criture \u00e0 ce d\u00e9p\u00f4t. Si le d\u00e9p\u00f4t de l&rsquo;action est compromis, chaque pipeline qui le r\u00e9f\u00e9rence devient \u00e9galement compromis.<\/p>\n<h3>Typosquatting<\/h3>\n<p>Les attaques par typosquatting exploitent les fautes d&rsquo;orthographe courantes et les similarit\u00e9s visuelles dans les noms de packages. Par exemple, enregistrer <code>co1ors<\/code> (avec le chiffre un) au lieu de <code>colors<\/code>, <code>lodahs<\/code> au lieu de <code>lodash<\/code>, ou <code>reqeusts<\/code> au lieu de <code>requests<\/code>. Ces packages contiennent du code malveillant et comptent sur les erreurs typographiques des d\u00e9veloppeurs lors de l&rsquo;ajout de d\u00e9pendances. Des outils automatis\u00e9s ont d\u00e9tect\u00e9 des milliers de packages de typosquatting sur npm et PyPI.<\/p>\n<h3>Comptes de mainteneurs pirat\u00e9s<\/h3>\n<p>Lorsqu&rsquo;un attaquant acc\u00e8de au compte d&rsquo;un mainteneur de package l\u00e9gitime \u2014 par le biais de credential stuffing, de phishing ou d&rsquo;ing\u00e9nierie sociale \u2014 il peut publier des versions contenant des portes d\u00e9rob\u00e9es de packages largement utilis\u00e9s. Comme le nom du package et le mainteneur sont l\u00e9gitimes, ces versions compromises sont extr\u00eamement difficiles \u00e0 d\u00e9tecter par des moyens automatis\u00e9s.<\/p>\n<h3>Plugins d&rsquo;outils de build<\/h3>\n<p>Les syst\u00e8mes de build comme Gradle, Maven et webpack prennent en charge des plugins qui s&rsquo;ex\u00e9cutent pendant le processus de build. Des plugins malveillants ou compromis dans ces \u00e9cosyst\u00e8mes peuvent modifier les r\u00e9sultats du build, exfiltrer des secrets ou injecter des portes d\u00e9rob\u00e9es dans les artefacts compil\u00e9s. Comme les plugins de build sont souvent moins scrut\u00e9s que les d\u00e9pendances applicatives, ils repr\u00e9sentent une cible \u00e0 haute valeur.<\/p>\n<h3>Incidents r\u00e9els<\/h3>\n<p>Plusieurs incidents majeurs illustrent l&rsquo;impact r\u00e9el de l&rsquo;artifact poisoning :<\/p>\n<ul>\n<li><strong>event-stream (2018) :<\/strong> Un nouveau mainteneur a obtenu les droits de publication sur le package npm populaire <code>event-stream<\/code> (1,5 million de t\u00e9l\u00e9chargements hebdomadaires). Il a ajout\u00e9 une d\u00e9pendance vers un package malveillant, <code>flatmap-stream<\/code>, qui contenait du code chiffr\u00e9 ciblant le portefeuille Bitcoin Copay, tentant de voler des cryptomonnaies.<\/li>\n<li><strong>ua-parser-js (2021) :<\/strong> Le package npm <code>ua-parser-js<\/code> (7 millions de t\u00e9l\u00e9chargements hebdomadaires) a \u00e9t\u00e9 d\u00e9tourn\u00e9 lorsque le compte du mainteneur a \u00e9t\u00e9 compromis. Des versions malveillantes ont \u00e9t\u00e9 publi\u00e9es, installant des cryptomineurs et des malwares de vol d&rsquo;identifiants sur les syst\u00e8mes Linux et Windows.<\/li>\n<li><strong>node-ipc (2022) :<\/strong> Le mainteneur du package <code>node-ipc<\/code> a d\u00e9lib\u00e9r\u00e9ment ajout\u00e9 du code qui effa\u00e7ait les fichiers sur les syst\u00e8mes ayant des adresses IP russes ou bi\u00e9lorusses, d\u00e9montrant que m\u00eame des mainteneurs de confiance peuvent devenir un vecteur de menace (parfois appel\u00e9 \u00ab protestware \u00bb).<\/li>\n<\/ul>\n<h2>Comment ces attaques exploitent le CI\/CD<\/h2>\n<p>Les pipelines CI\/CD sont particuli\u00e8rement vuln\u00e9rables \u00e0 la dependency confusion et \u00e0 l&rsquo;artifact poisoning en raison de leur mode de fonctionnement. Comprendre pourquoi les pipelines sont des cibles privil\u00e9gi\u00e9es est essentiel pour construire des d\u00e9fenses efficaces.<\/p>\n<h3>Ex\u00e9cution automatique de code pendant les builds<\/h3>\n<p>Chaque fois qu&rsquo;un pipeline CI ex\u00e9cute <code>npm install<\/code>, <code>pip install -r requirements.txt<\/code> ou <code>docker build<\/code>, il ex\u00e9cute du code provenant de sources externes. Cela se produit automatiquement \u00e0 chaque commit, pull request ou build planifi\u00e9. Il n&rsquo;y a aucun humain dans la boucle pour v\u00e9rifier quel code est r\u00e9ellement r\u00e9cup\u00e9r\u00e9 et ex\u00e9cut\u00e9.<\/p>\n<h3>Les environnements de build ont acc\u00e8s aux identifiants<\/h3>\n<p>Les environnements CI\/CD sont g\u00e9n\u00e9ralement configur\u00e9s avec les secrets n\u00e9cessaires au d\u00e9ploiement : identifiants de fournisseurs cloud, tokens API, mots de passe de bases de donn\u00e9es, cl\u00e9s de signature et identifiants de registre. Une d\u00e9pendance malveillante qui s&rsquo;ex\u00e9cute pendant la phase de build peut acc\u00e9der \u00e0 ces secrets via les variables d&rsquo;environnement ou les magasins de secrets mont\u00e9s. Cela fait des pipelines CI\/CD des cibles bien plus pr\u00e9cieuses que les ordinateurs portables des d\u00e9veloppeurs.<\/p>\n<h3>Les d\u00e9pendances r\u00e9cup\u00e9r\u00e9es au moment du build ne sont pas pr\u00e9-audit\u00e9es<\/h3>\n<p>Dans la plupart des organisations, les versions de d\u00e9pendances sont sp\u00e9cifi\u00e9es dans des fichiers manifestes (<code>package.json<\/code>, <code>requirements.txt<\/code>) mais le code r\u00e9el est r\u00e9cup\u00e9r\u00e9 \u00e0 neuf depuis les registres au moment du build. Entre le moment o\u00f9 un d\u00e9veloppeur ajoute une d\u00e9pendance et celui o\u00f9 le syst\u00e8me CI l&rsquo;installe, le contenu du package peut changer \u2014 ou un package de dependency confusion peut appara\u00eetre sur le registre public. Il n&rsquo;y a g\u00e9n\u00e9ralement aucune \u00e9tape de v\u00e9rification entre la r\u00e9solution et l&rsquo;ex\u00e9cution.<\/p>\n<h3>Les d\u00e9pendances transitives \u00e9largissent la surface d&rsquo;attaque<\/h3>\n<p>Votre application peut d\u00e9clarer 50 d\u00e9pendances directes, mais ces d\u00e9pendances ont leurs propres d\u00e9pendances, cr\u00e9ant un arbre qui peut inclure des milliers de packages transitifs. Vous n&rsquo;avez aucun contr\u00f4le direct sur les d\u00e9pendances de vos d\u00e9pendances. Lorsqu&rsquo;une d\u00e9pendance transitive est compromise \u2014 comme dans l&rsquo;incident <code>event-stream<\/code> \u2014 l&rsquo;attaque se propage \u00e0 travers tout l&rsquo;arbre de d\u00e9pendances sans aucune modification de vos propres fichiers manifestes.<\/p>\n<h2>Se d\u00e9fendre contre la Dependency Confusion<\/h2>\n<p>Pr\u00e9venir la dependency confusion n\u00e9cessite de configurer vos gestionnaires de packages et vos registres pour \u00e9liminer l&rsquo;ambigu\u00eft\u00e9 entre les packages publics et priv\u00e9s. Voici les mesures d&rsquo;att\u00e9nuation les plus efficaces.<\/p>\n<h3>Nommez et scopez vos packages priv\u00e9s<\/h3>\n<p>La d\u00e9fense la plus efficace consiste \u00e0 utiliser des noms de packages avec namespace ou scope pour tous les packages internes. Dans npm, cela signifie utiliser des packages scop\u00e9s comme <code>@yourcompany\/package-name<\/code>. Un attaquant ne peut pas enregistrer de packages sous le scope de votre organisation sur le registre public npm.<\/p>\n<h3>Configurez explicitement la priorit\u00e9 des registres<\/h3>\n<p>Ne vous fiez jamais au comportement de r\u00e9solution par d\u00e9faut. Configurez explicitement votre gestionnaire de packages pour r\u00e9cup\u00e9rer les packages scop\u00e9s depuis votre registre priv\u00e9 et tout le reste depuis le registre public.<\/p>\n<p><strong>Exemple de configuration <code>.npmrc<\/code> :<\/strong><\/p>\n<pre><code># Always fetch @yourcompany scoped packages from private registry\n@yourcompany:registry=https:\/\/npm.yourcompany.com\/\n\n# All other packages come from the public npm registry\nregistry=https:\/\/registry.npmjs.org\/\n\n# Authentication for private registry\n\/\/npm.yourcompany.com\/:_authToken=${NPM_PRIVATE_TOKEN}<\/code><\/pre>\n<p><strong>Exemple <code>pip.conf<\/code> pour Python :<\/strong><\/p>\n<pre><code># IMPORTANT: Use --index-url (NOT --extra-index-url) for your private registry\n# --extra-index-url checks BOTH registries and picks the higher version (vulnerable!)\n# --index-url uses ONLY your private registry as the primary source\n\n[global]\nindex-url = https:\/\/pypi.yourcompany.com\/simple\/\n\n# If you need public PyPI packages, configure your private registry\n# (Artifactory, Nexus) to proxy public PyPI \u2014 do NOT use --extra-index-url<\/code><\/pre>\n<p><strong>Exemple <code>.yarnrc.yml<\/code> pour Yarn Berry :<\/strong><\/p>\n<pre><code>npmScopes:\n  yourcompany:\n    npmRegistryServer: \"https:\/\/npm.yourcompany.com\"\n    npmAuthToken: \"${NPM_PRIVATE_TOKEN}\"\n\nnpmRegistryServer: \"https:\/\/registry.yarnpkg.com\"<\/code><\/pre>\n<h3>Utilisez des proxys de registres priv\u00e9s<\/h3>\n<p>D\u00e9ployez un proxy de registre tel que JFrog Artifactory, Sonatype Nexus ou GitHub Packages qui s&rsquo;interpose entre vos syst\u00e8mes de build et les registres publics. Configurez le proxy pour :<\/p>\n<ul>\n<li>Servir les packages internes depuis votre d\u00e9p\u00f4t priv\u00e9.<\/li>\n<li>Faire le proxy des packages publics depuis le registre en amont.<\/li>\n<li>Bloquer tout package public qui partage un nom avec un package interne.<\/li>\n<li>Appliquer des politiques de s\u00e9curit\u00e9 (analyse de vuln\u00e9rabilit\u00e9s, conformit\u00e9 des licences) avant d&rsquo;autoriser le passage des packages.<\/li>\n<\/ul>\n<p>Cela cr\u00e9e une source unique de v\u00e9rit\u00e9 pour toutes les d\u00e9pendances et \u00e9limine enti\u00e8rement l&rsquo;ambigu\u00eft\u00e9 public\/priv\u00e9.<\/p>\n<h3>Enregistrement d\u00e9fensif<\/h3>\n<p>Enregistrez vos noms de packages internes sur les registres publics en tant que packages de remplacement. Ces packages ne doivent contenir aucun code r\u00e9el \u2014 juste un README expliquant que le nom est r\u00e9serv\u00e9. Cela emp\u00eache les attaquants de revendiquer ces noms. Bien qu&rsquo;il ne s&rsquo;agisse pas d&rsquo;une d\u00e9fense principale, cela ajoute une couche de protection suppl\u00e9mentaire.<\/p>\n<h3>\u00c9pinglez les d\u00e9pendances par hash<\/h3>\n<p>L&rsquo;\u00e9pinglage des d\u00e9pendances par hash cryptographique garantit que l&rsquo;artefact exact que vous avez audit\u00e9 est bien celui install\u00e9 pendant les builds. M\u00eame si un attaquant publie une version malveillante, le hash ne correspondra pas et l&rsquo;installation \u00e9chouera.<\/p>\n<p><strong>Pour pip (Python) :<\/strong><\/p>\n<pre><code># Generate hashes for your requirements\npip-compile --generate-hashes requirements.in -o requirements.txt\n\n# Install with hash verification\npip install --require-hashes -r requirements.txt<\/code><\/pre>\n<p><strong>Pour npm :<\/strong><\/p>\n<p>npm enregistre automatiquement les hashes d&rsquo;int\u00e9grit\u00e9 dans <code>package-lock.json<\/code>. Assurez-vous de commiter le fichier de verrouillage et d&rsquo;utiliser <code>npm ci<\/code> (et non <code>npm install<\/code>) en CI pour appliquer la v\u00e9rification d&rsquo;int\u00e9grit\u00e9 :<\/p>\n<pre><code># In CI, always use npm ci \u2014 it strictly follows the lockfile\n# and verifies integrity hashes for every package\nnpm ci<\/code><\/pre>\n<h2>Se d\u00e9fendre contre l&rsquo;Artifact Poisoning<\/h2>\n<p>Parce que l&rsquo;artifact poisoning englobe un \u00e9ventail plus large de vecteurs d&rsquo;attaque, la d\u00e9fense n\u00e9cessite des contr\u00f4les en couches sur les images de conteneurs, les templates CI, les d\u00e9pendances et les processus de build.<\/p>\n<h3>\u00c9pinglez les images de conteneurs par digest<\/h3>\n<p>Ne r\u00e9f\u00e9rencez jamais les images de conteneurs par des tags mutables comme <code>latest<\/code> ou m\u00eame <code>3.11<\/code>. \u00c9pinglez plut\u00f4t au digest SHA256 immuable :<\/p>\n<pre><code># Vulnerable: tag can be overwritten with a compromised image\nFROM python:3.11-slim\n\n# Secure: digest is immutable \u2014 this exact image or nothing\nFROM python:3.11-slim@sha256:a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2<\/code><\/pre>\n<h3>\u00c9pinglez les GitHub Actions par SHA<\/h3>\n<p>R\u00e9f\u00e9rencez les GitHub Actions par leur SHA de commit complet plut\u00f4t que par un tag mutable :<\/p>\n<pre><code># Vulnerable: v3 tag can be moved to point to compromised code\n- uses: actions\/checkout@v3\n\n# Secure: pinned to specific commit SHA\n- uses: actions\/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2<\/code><\/pre>\n<h3>V\u00e9rifiez les signatures des d\u00e9pendances<\/h3>\n<p>Lorsque c&rsquo;est possible, v\u00e9rifiez les signatures cryptographiques pour confirmer que les artefacts ont \u00e9t\u00e9 publi\u00e9s par leurs mainteneurs attendus :<\/p>\n<ul>\n<li><strong>npm :<\/strong> Utilisez <code>npm audit signatures<\/code> pour v\u00e9rifier les signatures du registre sur les packages.<\/li>\n<li><strong>Images de conteneurs :<\/strong> Utilisez Sigstore\/cosign pour v\u00e9rifier les signatures des images de conteneurs.<\/li>\n<li><strong>Python :<\/strong> La PEP 740 et des outils comme <code>sigstore-python<\/code> apportent la v\u00e9rification de signatures \u00e0 PyPI.<\/li>\n<\/ul>\n<h3>G\u00e9n\u00e9rez et suivez les SBOMs<\/h3>\n<p>Un Software Bill of Materials (SBOM) inventorie chaque composant de votre application. En g\u00e9n\u00e9rant des SBOMs pour chaque build et en les comparant, vous pouvez d\u00e9tecter des ajouts ou modifications inattendus dans votre arbre de d\u00e9pendances. Des outils comme Syft, Trivy et CycloneDX peuvent g\u00e9n\u00e9rer des SBOMs dans des formats standards (SPDX, CycloneDX).<\/p>\n<h3>Automatisez la revue des d\u00e9pendances<\/h3>\n<p>D\u00e9ployez des outils automatis\u00e9s qui analysent continuellement vos d\u00e9pendances \u00e0 la recherche de vuln\u00e9rabilit\u00e9s connues et de changements suspects :<\/p>\n<ul>\n<li><strong>Dependabot \/ Renovate :<\/strong> Cr\u00e9ent automatiquement des PR lorsque des mises \u00e0 jour de d\u00e9pendances sont disponibles, vous donnant l&rsquo;occasion de les examiner avant de les fusionner.<\/li>\n<li><strong>npm audit \/ pip-audit :<\/strong> Analysent les vuln\u00e9rabilit\u00e9s connues dans votre arbre de d\u00e9pendances.<\/li>\n<li><strong>GitHub Dependency Review Action :<\/strong> Bloque les PR qui introduisent des d\u00e9pendances avec des vuln\u00e9rabilit\u00e9s connues.<\/li>\n<\/ul>\n<h3>Restreignez l&rsquo;acc\u00e8s r\u00e9seau pendant les builds (builds herm\u00e9tiques)<\/h3>\n<p>Les builds herm\u00e9tiques sont des builds qui ne peuvent pas acc\u00e9der au r\u00e9seau. Toutes les d\u00e9pendances doivent \u00eatre pr\u00e9-r\u00e9cup\u00e9r\u00e9es et mises en cache avant le d\u00e9but du build. Cela emp\u00eache un build de r\u00e9cup\u00e9rer un package malveillant nouvellement publi\u00e9. Bazel prend nativement en charge les builds herm\u00e9tiques, et une isolation similaire peut \u00eatre obtenue avec le flag <code>--network=none<\/code> de Docker ou des politiques r\u00e9seau sp\u00e9cifiques \u00e0 la plateforme CI.<\/p>\n<h3>Pr\u00e9-approuvez et \u00e9tablissez une liste d&rsquo;autorisation des d\u00e9pendances<\/h3>\n<p>Maintenez une liste approuv\u00e9e de d\u00e9pendances et de leurs versions. Tout nouveau changement de d\u00e9pendance ou de version n\u00e9cessite une approbation explicite via un processus de revue. Bien que cela ajoute de la friction, cela emp\u00eache les packages non autoris\u00e9s d&rsquo;entrer dans votre pipeline de build.<\/p>\n<h2>D\u00e9tection et surveillance<\/h2>\n<p>M\u00eame avec des contr\u00f4les pr\u00e9ventifs solides, les capacit\u00e9s de d\u00e9tection sont essentielles pour intercepter les attaques qui contournent vos d\u00e9fenses.<\/p>\n<h3>Surveillez les nouvelles d\u00e9pendances inattendues<\/h3>\n<p>Impl\u00e9mentez des v\u00e9rifications CI qui signalent les pull requests introduisant de nouvelles d\u00e9pendances. Exigez une justification explicite et une revue pour tout ajout \u00e0 votre manifeste de d\u00e9pendances. C&rsquo;est particuli\u00e8rement important pour les d\u00e9pendances transitives \u2014 une nouvelle d\u00e9pendance directe peut en apporter des dizaines de transitives.<\/p>\n<h3>Alertez sur les sauts de version des d\u00e9pendances<\/h3>\n<p>Une d\u00e9pendance passant de la version <code>1.2.3<\/code> \u00e0 <code>99.0.0<\/code> est un indicateur fort d&rsquo;une attaque par dependency confusion. Impl\u00e9mentez une surveillance qui alerte sur les changements de version inhabituels, en particulier les sauts majeurs de version importants sur les packages internes.<\/p>\n<h3>Tirez parti des outils d&rsquo;analyse de s\u00e9curit\u00e9<\/h3>\n<ul>\n<li><strong>Socket.dev :<\/strong> Analyse le comportement des packages (acc\u00e8s r\u00e9seau, acc\u00e8s au syst\u00e8me de fichiers, scripts d&rsquo;installation) plut\u00f4t que les seuls CVE connus, ce qui le rend efficace pour d\u00e9tecter les attaques sur la cha\u00eene d&rsquo;approvisionnement.<\/li>\n<li><strong>Snyk :<\/strong> Fournit une analyse et une surveillance des vuln\u00e9rabilit\u00e9s sur plusieurs \u00e9cosyst\u00e8mes.<\/li>\n<li><strong>GitHub Dependency Graph et Dependabot Alerts :<\/strong> Suivent automatiquement les d\u00e9pendances et alertent sur les vuln\u00e9rabilit\u00e9s connues.<\/li>\n<\/ul>\n<h3>Analysez les scripts d&rsquo;installation et les hooks post-installation<\/h3>\n<p>Impl\u00e9mentez des outils qui identifient sp\u00e9cifiquement les packages avec des scripts d&rsquo;installation. Bien que les scripts d&rsquo;installation aient des usages l\u00e9gitimes, ils sont le principal vecteur d&rsquo;ex\u00e9cution des attaques par dependency confusion. Signalez et examinez tout package qui inclut des scripts <code>preinstall<\/code>, <code>install<\/code> ou <code>postinstall<\/code> dans npm, ou un <code>setup.py<\/code> avec du code ex\u00e9cutable en Python.<\/p>\n<h3>Comparez les SBOMs entre les builds<\/h3>\n<p>Effectuez r\u00e9guli\u00e8rement un diff des SBOMs entre des builds cons\u00e9cutifs. Les changements inattendus \u2014 nouveaux packages apparaissant, versions changeant sans mises \u00e0 jour correspondantes du manifeste, ou packages provenant de registres inattendus \u2014 devraient d\u00e9clencher des alertes et une investigation.<\/p>\n<h2>Durcissement sp\u00e9cifique au CI\/CD<\/h2>\n<p>Au-del\u00e0 de la gestion des d\u00e9pendances, la configuration de votre pipeline CI\/CD elle-m\u00eame doit \u00eatre durcie pour r\u00e9sister aux attaques sur la cha\u00eene d&rsquo;approvisionnement.<\/p>\n<h3>Commitez et v\u00e9rifiez les fichiers de verrouillage en CI<\/h3>\n<p>Les fichiers de verrouillage (<code>package-lock.json<\/code>, <code>yarn.lock<\/code>, <code>Pipfile.lock<\/code>, <code>poetry.lock<\/code>) enregistrent les versions et hashes exacts de chaque d\u00e9pendance. Votre pipeline CI devrait \u00e9chouer si le fichier de verrouillage pr\u00e9sente des changements inattendus.<\/p>\n<p><strong>Exemple GitHub Actions \u2014 v\u00e9rification de l&rsquo;int\u00e9grit\u00e9 du lockfile :<\/strong><\/p>\n<pre><code>name: Build\non: [push, pull_request]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2\n\n      - name: Setup Node.js\n        uses: actions\/setup-node@1a4442cacd436585916f1b3aa94e4166f1a22160 # v3.8.2\n        with:\n          node-version: '20'\n\n      - name: Verify lockfile has not been tampered with\n        run: |\n          # npm ci will fail if package-lock.json is out of sync\n          # with package.json or if integrity hashes don't match\n          npm ci\n\n      - name: Check for lockfile modifications\n        run: |\n          if ! git diff --exit-code package-lock.json; then\n            echo \"ERROR: package-lock.json was modified during install.\"\n            echo \"This could indicate a dependency confusion attack.\"\n            exit 1\n          fi\n\n      - name: Audit dependencies\n        run: npm audit --audit-level=high<\/code><\/pre>\n<p><strong>Exemple GitLab CI \u2014 v\u00e9rification du lockfile avec pip :<\/strong><\/p>\n<pre><code>stages:\n  - verify\n  - build\n  - test\n\nverify-dependencies:\n  stage: verify\n  image: python:3.11-slim@sha256:abc123...  # Pin by digest\n  script:\n    - pip install pip-tools pip-audit\n    # Verify that requirements.txt hashes match actual packages\n    - pip install --require-hashes --no-deps -r requirements.txt\n    # Audit for known vulnerabilities\n    - pip-audit -r requirements.txt\n    # Ensure no unexpected changes to lockfile\n    - pip-compile --generate-hashes requirements.in -o \/tmp\/requirements-check.txt\n    - diff requirements.txt \/tmp\/requirements-check.txt\n  rules:\n    - if: '$CI_PIPELINE_SOURCE == \"merge_request_event\"'\n    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'\n\nbuild:\n  stage: build\n  image: python:3.11-slim@sha256:abc123...\n  script:\n    - pip install --require-hashes --no-deps -r requirements.txt\n    - python -m build\n  needs: [verify-dependencies]<\/code><\/pre>\n<h3>S\u00e9parez la r\u00e9solution des d\u00e9pendances de l&rsquo;ex\u00e9cution du build<\/h3>\n<p>Utilisez un processus de build en deux phases : d&rsquo;abord r\u00e9solvez et t\u00e9l\u00e9chargez les d\u00e9pendances dans un environnement isol\u00e9, puis ex\u00e9cutez le build r\u00e9el avec l&rsquo;acc\u00e8s r\u00e9seau d\u00e9sactiv\u00e9. Cela emp\u00eache une d\u00e9pendance compromise d&rsquo;exfiltrer des donn\u00e9es ou de t\u00e9l\u00e9charger des charges utiles suppl\u00e9mentaires pendant le build.<\/p>\n<h3>Environnements de build isol\u00e9s ou \u00e0 acc\u00e8s r\u00e9seau restreint<\/h3>\n<p>Pour les builds \u00e0 haute s\u00e9curit\u00e9, utilisez des environnements \u00e0 acc\u00e8s r\u00e9seau restreint qui ne peuvent acc\u00e9der qu&rsquo;\u00e0 votre proxy de registre interne. Cela \u00e9limine la possibilit\u00e9 que des d\u00e9pendances soient r\u00e9cup\u00e9r\u00e9es directement depuis les registres publics pendant le build.<\/p>\n<pre><code># Docker-based hermetic build example\n# Phase 1: Fetch dependencies (with network)\ndocker run --name dep-fetch my-builder:latest \\\n  npm ci --prefer-offline\n\n# Phase 2: Build (without network)\ndocker run --network=none -v deps:\/app\/node_modules \\\n  my-builder:latest npm run build<\/code><\/pre>\n<h3>Mettez en cache les d\u00e9pendances dans un stockage interne de confiance<\/h3>\n<p>Au lieu de r\u00e9cup\u00e9rer les d\u00e9pendances depuis les registres publics \u00e0 chaque build, mettez en cache les versions approuv\u00e9es dans un stockage interne (Artifactory, Nexus, buckets de stockage cloud). Votre pipeline CI devrait puiser exclusivement dans ce cache de confiance. Mettez \u00e0 jour le cache via un processus contr\u00f4l\u00e9 et audit\u00e9.<\/p>\n<h2>Conclusion<\/h2>\n<p>La dependency confusion et l&rsquo;artifact poisoning exploitent des hypoth\u00e8ses de confiance profond\u00e9ment ancr\u00e9es dans la cha\u00eene d&rsquo;approvisionnement logicielle. Chaque <code>npm install<\/code>, chaque <code>docker pull<\/code>, chaque directive <code>uses:<\/code> dans un workflow GitHub Actions est une d\u00e9cision de confiance \u2014 et les attaquants travaillent activement pour abuser de cette confiance.<\/p>\n<p>Une d\u00e9fense efficace ne repose pas sur un seul outil ou changement de configuration. Elle n\u00e9cessite des contr\u00f4les \u00e0 chaque couche du cycle de vie des d\u00e9pendances :<\/p>\n<ul>\n<li><strong>R\u00e9solution :<\/strong> Scopez vos packages, configurez la priorit\u00e9 des registres, utilisez des proxys de registres pour \u00e9liminer l&rsquo;ambigu\u00eft\u00e9 public\/priv\u00e9.<\/li>\n<li><strong>Installation :<\/strong> \u00c9pinglez par hash, utilisez les fichiers de verrouillage avec <code>npm ci<\/code> ou <code>--require-hashes<\/code>, d\u00e9sactivez les scripts d&rsquo;installation lorsque c&rsquo;est possible.<\/li>\n<li><strong>V\u00e9rification :<\/strong> V\u00e9rifiez les signatures, comparez les SBOMs, auditez les d\u00e9pendances avant qu&rsquo;elles n&rsquo;entrent dans votre build.<\/li>\n<li><strong>Surveillance :<\/strong> D\u00e9tectez les changements de d\u00e9pendances inattendus, alertez sur les anomalies de version, analysez les comportements malveillants dans les packages.<\/li>\n<li><strong>Durcissement du pipeline :<\/strong> Restreignez l&rsquo;acc\u00e8s r\u00e9seau pendant les builds, v\u00e9rifiez l&rsquo;int\u00e9grit\u00e9 des fichiers de verrouillage en CI, s\u00e9parez la r\u00e9solution des d\u00e9pendances de l&rsquo;ex\u00e9cution du build.<\/li>\n<\/ul>\n<p>Les organisations les plus r\u00e9silientes face aux attaques sur la cha\u00eene d&rsquo;approvisionnement seront celles qui traitent les d\u00e9pendances avec la m\u00eame rigueur qu&rsquo;elles appliquent \u00e0 leur propre code : revues, v\u00e9rifi\u00e9es, surveill\u00e9es et jamais implicitement fiables. Commencez par impl\u00e9menter les contr\u00f4les \u00e0 plus fort impact \u2014 packages scop\u00e9s, configuration des registres, v\u00e9rification des fichiers de verrouillage en CI \u2014 et ajoutez progressivement des couches au fur et \u00e0 mesure que votre programme de s\u00e9curit\u00e9 de la cha\u00eene d&rsquo;approvisionnement m\u00fbrit.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Les attaques contre la cha\u00eene d&rsquo;approvisionnement logicielle ont connu une augmentation consid\u00e9rable, tant en fr\u00e9quence qu&rsquo;en sophistication, au cours des derni\u00e8res ann\u00e9es. Plut\u00f4t que d&rsquo;attaquer directement les applications, les adversaires ciblent de plus en plus les couches de r\u00e9solution de d\u00e9pendances et de distribution d&rsquo;artefacts qui sous-tendent le d\u00e9veloppement logiciel moderne. Deux des techniques &#8230; <a title=\"Confusion de D\u00e9pendances et Empoisonnement d&rsquo;Artefacts : Techniques d&rsquo;Attaque et D\u00e9fenses\" class=\"read-more\" href=\"https:\/\/secure-pipelines.com\/fr\/ci-cd-security\/dependency-confusion-artifact-poisoning-attacks-defenses\/\" aria-label=\"En savoir plus sur Confusion de D\u00e9pendances et Empoisonnement d&rsquo;Artefacts : Techniques d&rsquo;Attaque et D\u00e9fenses\">Lire la suite<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[49,54],"tags":[],"post_folder":[],"class_list":["post-502","post","type-post","status-publish","format-standard","hentry","category-ci-cd-security","category-threats-attacks"],"_links":{"self":[{"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/posts\/502","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/comments?post=502"}],"version-history":[{"count":1,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/posts\/502\/revisions"}],"predecessor-version":[{"id":514,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/posts\/502\/revisions\/514"}],"wp:attachment":[{"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/media?parent=502"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/categories?post=502"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/tags?post=502"},{"taxonomy":"post_folder","embeddable":true,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/post_folder?post=502"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}