{"id":485,"date":"2026-01-30T22:17:45","date_gmt":"2026-01-30T21:17:45","guid":{"rendered":"https:\/\/secure-pipelines.com\/?p=485"},"modified":"2026-03-24T10:46:29","modified_gmt":"2026-03-24T09:46:29","slug":"ci-cd-execution-models-trust-assumptions-security-guide-2","status":"publish","type":"post","link":"https:\/\/secure-pipelines.com\/fr\/ci-cd-security\/ci-cd-execution-models-trust-assumptions-security-guide-2\/","title":{"rendered":"Mod\u00e8les d&rsquo;Ex\u00e9cution CI\/CD et Hypoth\u00e8ses de Confiance : Guide de S\u00e9curit\u00e9"},"content":{"rendered":"<h2>Introduction<\/h2>\n<p>Les pipelines CI\/CD figurent parmi les composants les plus privil\u00e9gi\u00e9s de toute organisation logicielle moderne. Ils clonent le code source, acc\u00e8dent aux secrets, construisent des artefacts et d\u00e9ploient en production \u2014 souvent avec une supervision humaine minimale. Pourtant, malgr\u00e9 ce niveau d&rsquo;acc\u00e8s extraordinaire, les mod\u00e8les de confiance qui sous-tendent ces pipelines sont rarement rendus explicites.<\/p>\n<p>Lorsqu&rsquo;un pipeline s&rsquo;ex\u00e9cute, il r\u00e9pond implicitement \u00e0 une cha\u00eene de questions de s\u00e9curit\u00e9 : Qui a d\u00e9clench\u00e9 cette ex\u00e9cution ? Quel code est ex\u00e9cut\u00e9 ? Quelle identit\u00e9 le pipeline assume-t-il ? Quelles ressources peut-il atteindre ? Dans la plupart des organisations, ces questions trouvent leur r\u00e9ponse dans les configurations par d\u00e9faut plut\u00f4t que dans des d\u00e9cisions de s\u00e9curit\u00e9 d\u00e9lib\u00e9r\u00e9es.<\/p>\n<p>Ce guide cartographie le fonctionnement des diff\u00e9rents mod\u00e8les d&rsquo;ex\u00e9cution CI\/CD, les endroits o\u00f9 la confiance est suppos\u00e9e plut\u00f4t que v\u00e9rifi\u00e9e, et comment durcir vos pipelines contre les sch\u00e9mas d&rsquo;attaque r\u00e9els qui exploitent ces failles. Que vous utilisiez GitHub Actions, GitLab CI ou une autre plateforme, les dynamiques de confiance sous-jacentes sont universelles \u2014 et les comprendre est essentiel pour s\u00e9curiser votre cha\u00eene d&rsquo;approvisionnement logicielle.<\/p>\n<h2>Qu&rsquo;est-ce qu&rsquo;un mod\u00e8le d&rsquo;ex\u00e9cution CI\/CD ?<\/h2>\n<p>Un mod\u00e8le d&rsquo;ex\u00e9cution CI\/CD d\u00e9finit le cycle de vie complet de la mani\u00e8re dont le code du pipeline est d\u00e9clench\u00e9, o\u00f9 il s&rsquo;ex\u00e9cute physiquement, quelle identit\u00e9 il assume pendant l&rsquo;ex\u00e9cution et quelles ressources il peut atteindre. Il constitue, par essence, l&rsquo;architecture de s\u00e9curit\u00e9 de votre couche d&rsquo;automatisation.<\/p>\n<p>Chaque mod\u00e8le d&rsquo;ex\u00e9cution doit r\u00e9pondre \u00e0 quatre questions fondamentales :<\/p>\n<ul>\n<li><strong>D\u00e9clencheur :<\/strong> Quel \u00e9v\u00e9nement initie le pipeline, et qui ou quoi est autoris\u00e9 \u00e0 provoquer cet \u00e9v\u00e9nement ?<\/li>\n<li><strong>Environnement :<\/strong> O\u00f9 le code du pipeline s&rsquo;ex\u00e9cute-t-il \u2014 sur quelle infrastructure, avec quel syst\u00e8me d&rsquo;exploitation et avec quel degr\u00e9 d&rsquo;isolation ?<\/li>\n<li><strong>Identit\u00e9 :<\/strong> Quels identifiants, tokens ou comptes de service le pipeline en cours d&rsquo;ex\u00e9cution poss\u00e8de-t-il ?<\/li>\n<li><strong>Acc\u00e8s :<\/strong> Quels syst\u00e8mes en aval, secrets, registres et cibles de d\u00e9ploiement le pipeline peut-il atteindre ?<\/li>\n<\/ul>\n<p>La mani\u00e8re dont ces questions trouvent leur r\u00e9ponse varie consid\u00e9rablement selon les environnements d&rsquo;ex\u00e9cution :<\/p>\n<h3>Runners h\u00e9berg\u00e9s en SaaS<\/h3>\n<p>Les plateformes comme GitHub Actions (runners h\u00e9berg\u00e9s par GitHub) et les runners partag\u00e9s de GitLab.com fournissent des machines virtuelles \u00e9ph\u00e9m\u00e8res g\u00e9r\u00e9es par le fournisseur CI\/CD. Chaque job obtient g\u00e9n\u00e9ralement une VM neuve qui est d\u00e9truite apr\u00e8s l&rsquo;ex\u00e9cution. La plateforme g\u00e8re les mises \u00e0 jour, l&rsquo;isolation et le cycle de vie. Le compromis est que vous faites confiance aux garanties d&rsquo;isolation du fournisseur \u2014 vous ne pouvez ni inspecter ni contr\u00f4ler l&rsquo;infrastructure sous-jacente.<\/p>\n<h3>Runners auto-h\u00e9berg\u00e9s<\/h3>\n<p>Les organisations d\u00e9ploient leurs propres agents runner sur l&rsquo;infrastructure qu&rsquo;elles contr\u00f4lent \u2014 VMs, serveurs physiques ou pods Kubernetes. Cela offre un contr\u00f4le total sur l&rsquo;environnement d&rsquo;ex\u00e9cution mais transf\u00e8re enti\u00e8rement la responsabilit\u00e9 de l&rsquo;isolation, des mises \u00e0 jour et de la gestion des identifiants \u00e0 l&rsquo;op\u00e9rateur. Un runner auto-h\u00e9berg\u00e9 mal configur\u00e9 est l&rsquo;un des vecteurs les plus courants de mouvement lat\u00e9ral dans les attaques CI\/CD.<\/p>\n<h3>Ex\u00e9cution conteneuris\u00e9e<\/h3>\n<p>De nombreux pipelines ex\u00e9cutent les jobs \u00e0 l&rsquo;int\u00e9rieur de conteneurs, que ce soit sur une infrastructure auto-h\u00e9berg\u00e9e ou sur des clusters Kubernetes manag\u00e9s. L&rsquo;ex\u00e9cution bas\u00e9e sur les conteneurs fournit une isolation au niveau des processus et des environnements reproductibles, mais les conteneurs ne constituent pas des fronti\u00e8res de s\u00e9curit\u00e9 de la m\u00eame mani\u00e8re que les VMs. L&rsquo;acc\u00e8s partag\u00e9 au kernel, les volumes mont\u00e9s et l&rsquo;exposition du socket Docker peuvent tous compromettre le mod\u00e8le d&rsquo;isolation.<\/p>\n<h3>Ex\u00e9cution serverless et \u00e0 la demande<\/h3>\n<p>Certains syst\u00e8mes CI\/CD modernes (tels qu&rsquo;AWS CodeBuild ou certaines configurations Buildkite) provisionnent un calcul enti\u00e8rement \u00e0 la demande pour chaque job. Ces mod\u00e8les offrent de fortes garanties d&rsquo;isolation puisque chaque ex\u00e9cution obtient une instance de calcul d\u00e9di\u00e9e et \u00e9ph\u00e9m\u00e8re, mais ils introduisent une complexit\u00e9 autour du bootstrapping des identifiants et du contr\u00f4le d&rsquo;acc\u00e8s r\u00e9seau.<\/p>\n<p>Comprendre quel mod\u00e8le votre organisation utilise \u2014 et les propri\u00e9t\u00e9s de s\u00e9curit\u00e9 qu&rsquo;il fournit ou ne fournit pas \u2014 est le fondement du raisonnement sur la confiance CI\/CD.<\/p>\n<h2>Fronti\u00e8res de confiance dans le CI\/CD<\/h2>\n<p>Une fronti\u00e8re de confiance existe partout o\u00f9 le contr\u00f4le passe d&rsquo;une entit\u00e9 ou d&rsquo;un syst\u00e8me \u00e0 un autre. Dans le CI\/CD, il existe plusieurs fronti\u00e8res de confiance critiques, et les d\u00e9faillances \u00e0 n&rsquo;importe laquelle d&rsquo;entre elles peuvent mener \u00e0 une compromission compl\u00e8te du pipeline.<\/p>\n<h3>Du d\u00e9p\u00f4t de code source au d\u00e9clencheur du pipeline<\/h3>\n<p>La premi\u00e8re fronti\u00e8re de confiance se situe entre le d\u00e9p\u00f4t de code et le m\u00e9canisme de d\u00e9clenchement du pipeline. Lorsqu&rsquo;un d\u00e9veloppeur pousse un commit ou ouvre une pull request, la plateforme CI\/CD d\u00e9cide si et comment ex\u00e9cuter un pipeline. La question critique est : <strong>qui peut d\u00e9clencher l&rsquo;ex\u00e9cution du pipeline, et peut-il contr\u00f4ler quel code le pipeline ex\u00e9cute ?<\/strong><\/p>\n<p>Dans de nombreuses configurations, quiconque peut ouvrir une pull request \u2014 y compris les contributeurs externes aux d\u00e9p\u00f4ts publics \u2014 peut d\u00e9clencher l&rsquo;ex\u00e9cution du pipeline. Si la d\u00e9finition du pipeline elle-m\u00eame provient de la branche de la PR, le contributeur contr\u00f4le effectivement le code qui s&rsquo;ex\u00e9cute dans votre environnement CI.<\/p>\n<h3>De la d\u00e9finition du pipeline \u00e0 l&rsquo;environnement d&rsquo;ex\u00e9cution<\/h3>\n<p>La deuxi\u00e8me fronti\u00e8re de confiance s\u00e9pare la d\u00e9finition du pipeline (le fichier YAML, le Jenkinsfile, le script de build) de l&rsquo;environnement o\u00f9 il s&rsquo;ex\u00e9cute. Les questions cl\u00e9s incluent : Le runner a-t-il acc\u00e8s au r\u00e9seau ? Le pipeline peut-il installer des logiciels arbitraires ? Peut-il modifier le runner lui-m\u00eame pour les jobs futurs ?<\/p>\n<p>Sur les runners partag\u00e9s ou persistants, une d\u00e9finition de pipeline malveillante pourrait installer une porte d\u00e9rob\u00e9e qui persiste \u00e0 travers les ex\u00e9cutions de jobs ult\u00e9rieures \u2014 affectant des d\u00e9p\u00f4ts et des \u00e9quipes enti\u00e8rement diff\u00e9rents.<\/p>\n<h3>De l&rsquo;environnement d&rsquo;ex\u00e9cution aux secrets et identifiants<\/h3>\n<p>Les pipelines ont besoin d&rsquo;identifiants pour effectuer un travail utile : tokens API, cl\u00e9s de fournisseurs cloud, mots de passe de registres, cl\u00e9s de signature. La fronti\u00e8re de confiance entre l&rsquo;environnement d&rsquo;ex\u00e9cution et le magasin de secrets d\u00e9termine ce \u00e0 quoi un pipeline compromis peut acc\u00e9der. Un acc\u00e8s aux secrets trop large est l&rsquo;une des erreurs de configuration les plus courantes et les plus dangereuses dans le CI\/CD.<\/p>\n<h3>De la sortie du build \u00e0 la cible de d\u00e9ploiement<\/h3>\n<p>La derni\u00e8re fronti\u00e8re de confiance se situe entre ce que le pipeline produit (une image de conteneur, un binaire, un plan Terraform) et le syst\u00e8me o\u00f9 cette sortie est d\u00e9ploy\u00e9e. Si l&rsquo;identit\u00e9 du pipeline qui construit un artefact est la m\u00eame identit\u00e9 qui le d\u00e9ploie en production, il n&rsquo;y a pas de s\u00e9paration des responsabilit\u00e9s. Une seule \u00e9tape de build compromise peut mener directement \u00e0 une compromission de la production.<\/p>\n<h3>Cartographie des zones de confiance<\/h3>\n<p>Conceptuellement, un pipeline CI\/CD traverse quatre zones de confiance :<\/p>\n<pre><code>Zone 1: Contr\u00f4le de source (Postes de travail des d\u00e9veloppeurs, branches, PRs)\n   \u2193 [Fronti\u00e8re de d\u00e9clenchement]\nZone 2: D\u00e9finition du pipeline (YAML\/config analys\u00e9 par la plateforme CI)\n   \u2193 [Fronti\u00e8re d'ex\u00e9cution]\nZone 3: Environnement d'ex\u00e9cution (Runner, conteneur, VM \u2014 avec secrets)\n   \u2193 [Fronti\u00e8re de d\u00e9ploiement]\nZone 4: Cibles de d\u00e9ploiement (Production, staging, registres, APIs cloud)\n<\/code><\/pre>\n<p>Chaque fl\u00e8che repr\u00e9sente une fronti\u00e8re de confiance. Des contr\u00f4les de s\u00e9curit\u00e9 devraient exister \u00e0 chaque transition : r\u00e8gles de protection des branches \u00e0 la fronti\u00e8re de d\u00e9clenchement, isolation des runners \u00e0 la fronti\u00e8re d&rsquo;ex\u00e9cution, identifiants \u00e0 port\u00e9e limit\u00e9e \u00e0 la fronti\u00e8re des secrets, et approbations de d\u00e9ploiement \u00e0 la fronti\u00e8re de d\u00e9ploiement.<\/p>\n<h2>Mod\u00e8le d&rsquo;ex\u00e9cution GitHub Actions<\/h2>\n<p>GitHub Actions est l&rsquo;une des plateformes CI\/CD les plus largement adopt\u00e9es, et son mod\u00e8le d&rsquo;ex\u00e9cution poss\u00e8de plusieurs caract\u00e9ristiques de confiance uniques qu&rsquo;il convient de comprendre en profondeur.<\/p>\n<h3>Runners h\u00e9berg\u00e9s par GitHub vs runners auto-h\u00e9berg\u00e9s<\/h3>\n<p>Les runners h\u00e9berg\u00e9s par GitHub sont des VMs \u00e9ph\u00e9m\u00e8res provisionn\u00e9es par GitHub pour chaque job. Ils fonctionnent sur l&rsquo;infrastructure Azure, sont d\u00e9truits apr\u00e8s chaque ex\u00e9cution de job et fournissent une forte isolation entre les jobs. Les runners auto-h\u00e9berg\u00e9s, en revanche, sont des machines que vous enregistrez aupr\u00e8s de GitHub. Ils persistent entre les jobs, peuvent accumuler de l&rsquo;\u00e9tat et \u2014 point critique \u2014 tout d\u00e9p\u00f4t de l&rsquo;organisation ayant acc\u00e8s au runner peut ex\u00e9cuter du code dessus.<\/p>\n<p>Pour les runners auto-h\u00e9berg\u00e9s, GitHub avertit explicitement : <strong>n&rsquo;utilisez pas de runners auto-h\u00e9berg\u00e9s avec des d\u00e9p\u00f4ts publics.<\/strong> N&rsquo;importe quel fork peut soumettre une pull request qui d\u00e9clenche un workflow, et ce workflow s&rsquo;ex\u00e9cute sur votre infrastructure avec votre acc\u00e8s r\u00e9seau.<\/p>\n<h3>Permissions et port\u00e9e du GITHUB_TOKEN<\/h3>\n<p>Chaque ex\u00e9cution de workflow re\u00e7oit un <code>GITHUB_TOKEN<\/code> automatique avec des permissions limit\u00e9es au d\u00e9p\u00f4t. Par d\u00e9faut, ce token dispose de larges permissions de lecture\/\u00e9criture sur le contenu du d\u00e9p\u00f4t, les packages, les issues et plus encore. La cl\u00e9 <code>permissions<\/code> vous permet de restreindre ce token \u00e0 ce qui est strictement n\u00e9cessaire :<\/p>\n<pre><code>permissions:\n  contents: read\n  packages: write\n  id-token: write   # Pour la f\u00e9d\u00e9ration OIDC\n<\/code><\/pre>\n<p>D\u00e9finir les permissions au niveau sup\u00e9rieur \u00e0 <code>read-all<\/code> ou m\u00eame vides (<code>{}<\/code>) puis accorder des permissions sp\u00e9cifiques par job est une \u00e9tape de durcissement critique. Sans cela, toute \u00e9tape compromise dans n&rsquo;importe quel job dispose d&rsquo;un acc\u00e8s en \u00e9criture \u00e0 votre d\u00e9p\u00f4t.<\/p>\n<h3>Workflows de PR de forks : pull_request vs pull_request_target<\/h3>\n<p>C&rsquo;est l&rsquo;une des fronti\u00e8res de confiance les plus dangereuses dans GitHub Actions. L&rsquo;\u00e9v\u00e9nement <code>pull_request<\/code> ex\u00e9cute la d\u00e9finition du workflow depuis la branche head de la PR \u2014 ce qui signifie que le contributeur contr\u00f4le le code du workflow \u2014 mais de mani\u00e8re critique, il n&rsquo;a <strong>pas<\/strong> acc\u00e8s aux secrets du d\u00e9p\u00f4t. L&rsquo;\u00e9v\u00e9nement <code>pull_request_target<\/code> ex\u00e9cute le workflow depuis la branche <strong>base<\/strong> (la branche main de votre d\u00e9p\u00f4t) mais <strong>a<\/strong> acc\u00e8s aux secrets.<\/p>\n<p>Le danger survient lorsque les workflows <code>pull_request_target<\/code> font un checkout du code de la branche head de la PR :<\/p>\n<pre><code># DANGEREUX : pull_request_target avec checkout explicite du code de la PR\non: pull_request_target\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@v4\n        with:\n          ref: ${{ github.event.pull_request.head.sha }}\n      # Ceci ex\u00e9cute maintenant du CODE NON FIABLE avec acc\u00e8s aux SECRETS\n      - run: npm install && npm test\n<\/code><\/pre>\n<p>Ce pattern donne \u00e0 un attaquant la capacit\u00e9 d&rsquo;ex\u00e9cuter du code arbitraire avec acc\u00e8s aux secrets de votre d\u00e9p\u00f4t. C&rsquo;est l&rsquo;exemple canonique de Poisoned Pipeline Execution dans GitHub Actions.<\/p>\n<h3>Workflows r\u00e9utilisables et d\u00e9l\u00e9gation de confiance<\/h3>\n<p>Les workflows r\u00e9utilisables vous permettent de centraliser la logique de pipeline dans un d\u00e9p\u00f4t partag\u00e9 et de l&rsquo;appeler depuis d&rsquo;autres d\u00e9p\u00f4ts. Lorsqu&rsquo;un workflow r\u00e9utilisable est invoqu\u00e9, il s&rsquo;ex\u00e9cute avec les permissions et les secrets du workflow <strong>appelant<\/strong>. Cela cr\u00e9e une cha\u00eene de d\u00e9l\u00e9gation de confiance : vous faites confiance au code du workflow r\u00e9utilisable (dans un autre d\u00e9p\u00f4t) pour g\u00e9rer vos secrets de mani\u00e8re responsable.<\/p>\n<p>\u00c9pinglez les workflows r\u00e9utilisables \u00e0 un SHA de commit sp\u00e9cifique, pas \u00e0 une branche ou un tag :<\/p>\n<pre><code>jobs:\n  deploy:\n    uses: my-org\/shared-workflows\/.github\/workflows\/deploy.yml@a1b2c3d4e5f6\n    secrets: inherit\n<\/code><\/pre>\n<h3>R\u00e8gles de protection des environnements<\/h3>\n<p>Les Environments GitHub fournissent une fronti\u00e8re de confiance critique pour les workflows de d\u00e9ploiement. Vous pouvez configurer des r\u00e9viseurs requis, des d\u00e9lais d&rsquo;attente et des restrictions de branches sur les environnements. Lorsqu&rsquo;un job r\u00e9f\u00e9rence un environnement, il doit satisfaire les r\u00e8gles de protection avant que les secrets associ\u00e9s \u00e0 cet environnement ne soient rendus disponibles :<\/p>\n<pre><code>jobs:\n  deploy-production:\n    runs-on: ubuntu-latest\n    environment:\n      name: production\n      url: https:\/\/example.com\n    steps:\n      - name: Deploy\n        run: .\/deploy.sh\n        env:\n          AWS_ACCESS_KEY_ID: ${{ secrets.PROD_AWS_KEY }}\n<\/code><\/pre>\n<p>Cela garantit que m\u00eame si un workflow est d\u00e9clench\u00e9, les identifiants de production ne sont pas expos\u00e9s sans approbation humaine.<\/p>\n<h2>Mod\u00e8le d&rsquo;ex\u00e9cution GitLab CI<\/h2>\n<p>GitLab CI poss\u00e8de un mod\u00e8le d&rsquo;ex\u00e9cution diff\u00e9rent avec ses propres caract\u00e9ristiques de confiance, notamment autour de la port\u00e9e des runners et de la protection des variables.<\/p>\n<h3>Runners partag\u00e9s vs runners de groupe vs runners de projet<\/h3>\n<p>GitLab offre trois niveaux de port\u00e9e pour les runners. Les <strong>runners partag\u00e9s<\/strong> (sur GitLab.com, ceux-ci sont g\u00e9r\u00e9s par GitLab) sont disponibles pour tous les projets. Les <strong>runners de groupe<\/strong> sont disponibles pour tous les projets au sein d&rsquo;un groupe GitLab. Les <strong>runners de projet<\/strong> sont d\u00e9di\u00e9s \u00e0 un seul projet. La port\u00e9e d\u00e9termine le rayon d&rsquo;impact d&rsquo;un runner compromis \u2014 une compromission de runner partag\u00e9 affecte tous les projets, tandis qu&rsquo;une compromission de runner de projet est contenue \u00e0 un seul projet.<\/p>\n<p>Pour les charges de travail sensibles, pr\u00e9f\u00e9rez toujours les runners sp\u00e9cifiques au projet avec un \u00e9tiquetage appropri\u00e9 :<\/p>\n<pre><code>deploy-production:\n  stage: deploy\n  tags:\n    - production-runner\n    - isolated\n  script:\n    - .\/deploy.sh\n  rules:\n    - if: $CI_COMMIT_BRANCH == \"main\"\n<\/code><\/pre>\n<h3>Branches prot\u00e9g\u00e9es et variables prot\u00e9g\u00e9es<\/h3>\n<p>Le m\u00e9canisme de variables prot\u00e9g\u00e9es de GitLab est un contr\u00f4le de confiance cl\u00e9. Les variables marqu\u00e9es comme \u00ab prot\u00e9g\u00e9es \u00bb ne sont expos\u00e9es qu&rsquo;aux pipelines s&rsquo;ex\u00e9cutant sur des branches prot\u00e9g\u00e9es ou des tags prot\u00e9g\u00e9s. Cela signifie qu&rsquo;un pipeline d\u00e9clench\u00e9 par une merge request depuis une branche de fonctionnalit\u00e9 \u2014 ou pire, depuis un fork \u2014 n&rsquo;aura pas acc\u00e8s aux variables prot\u00e9g\u00e9es.<\/p>\n<p>C&rsquo;est le m\u00e9canisme principal de GitLab pour emp\u00eacher l&rsquo;exposition des secrets au code non fiable :<\/p>\n<pre><code># Dans .gitlab-ci.yml, les variables prot\u00e9g\u00e9es ne sont disponibles que sur les branches prot\u00e9g\u00e9es\ndeploy:\n  stage: deploy\n  script:\n    - echo \"Deploying with $PRODUCTION_API_KEY\"\n  rules:\n    - if: $CI_COMMIT_BRANCH == \"main\"  # main est une branche prot\u00e9g\u00e9e\n  environment:\n    name: production\n<\/code><\/pre>\n<h3>Port\u00e9e et limitations du CI_JOB_TOKEN<\/h3>\n<p>Chaque job GitLab CI re\u00e7oit un <code>CI_JOB_TOKEN<\/code>, un token g\u00e9n\u00e9r\u00e9 automatiquement et limit\u00e9 au projet. Par d\u00e9faut, ce token peut acc\u00e9der aux ressources d&rsquo;autres projets, ce qui cr\u00e9e une relation de confiance implicite. GitLab vous permet de restreindre l&rsquo;acc\u00e8s du <code>CI_JOB_TOKEN<\/code> en configurant une liste blanche de projets accessibles \u2014 une \u00e9tape de durcissement critique qui limite le mouvement lat\u00e9ral si un pipeline est compromis.<\/p>\n<p>Dans les param\u00e8tres de votre projet sous <strong>CI\/CD \u2192 Token Access<\/strong>, restreignez la port\u00e9e du token aux seuls projets avec lesquels votre pipeline a v\u00e9ritablement besoin d&rsquo;interagir.<\/p>\n<h3>Pipelines de merge request et fronti\u00e8res de confiance<\/h3>\n<p>GitLab distingue les pipelines de branche et les pipelines de merge request. Les pipelines de merge request s&rsquo;ex\u00e9cutent dans le contexte de la merge request et ont acc\u00e8s \u00e0 un ensemble limit\u00e9 de variables pr\u00e9d\u00e9finies. Pour les pipelines d\u00e9clench\u00e9s par des merge requests provenant de forks, GitLab n&rsquo;expose pas les variables prot\u00e9g\u00e9es ni les secrets au niveau du projet \u2014 c&rsquo;est une fronti\u00e8re de confiance intentionnelle.<\/p>\n<p>Cependant, les pipelines s&rsquo;ex\u00e9cutant sur le <strong>r\u00e9sultat fusionn\u00e9<\/strong> (le <code>merge_request_event<\/code> avec les pipelines de r\u00e9sultats fusionn\u00e9s activ\u00e9s) ex\u00e9cutent toujours le code du fork. Si votre d\u00e9finition de pipeline permet l&rsquo;ex\u00e9cution de code arbitraire et que le job a acc\u00e8s aux secrets via des variables non prot\u00e9g\u00e9es, cela peut toujours \u00eatre exploit\u00e9.<\/p>\n<h2>D\u00e9faillances courantes des hypoth\u00e8ses de confiance<\/h2>\n<p>Comprendre les mod\u00e8les d&rsquo;ex\u00e9cution est important, mais la vraie valeur r\u00e9side dans la reconnaissance des patterns qui m\u00e8nent \u00e0 la compromission. Voici les d\u00e9faillances d&rsquo;hypoth\u00e8ses de confiance qui apparaissent de mani\u00e8re r\u00e9p\u00e9t\u00e9e dans les violations CI\/CD r\u00e9elles.<\/p>\n<h3>Poisoned Pipeline Execution (PPE)<\/h3>\n<p>Le Poisoned Pipeline Execution survient lorsqu&rsquo;un attaquant peut modifier la d\u00e9finition du pipeline qui s&rsquo;ex\u00e9cute dans un contexte privil\u00e9gi\u00e9. C&rsquo;est la classe de vuln\u00e9rabilit\u00e9 CI\/CD la plus r\u00e9pandue. Cela se produit lorsque :<\/p>\n<ul>\n<li>Une pull request d\u00e9clenche un workflow qui utilise la version du fichier pipeline de la PR<\/li>\n<li>Ce workflow a acc\u00e8s aux secrets ou aux identifiants de d\u00e9ploiement<\/li>\n<li>Il n&rsquo;y a pas de porte de r\u00e9vision ou d&rsquo;approbation entre la PR et l&rsquo;ex\u00e9cution du pipeline<\/li>\n<\/ul>\n<p>L&rsquo;attaquant modifie le YAML du pipeline (ou un script qu&rsquo;il appelle) pour exfiltrer les secrets, injecter des portes d\u00e9rob\u00e9es dans les artefacts de build, ou pivoter vers les syst\u00e8mes internes.<\/p>\n<h3>Supposer l&rsquo;isolation des runners sur une infrastructure partag\u00e9e<\/h3>\n<p>Lorsque plusieurs \u00e9quipes ou projets partagent des runners \u2014 en particulier des runners auto-h\u00e9berg\u00e9s \u2014 il existe souvent une hypoth\u00e8se implicite d&rsquo;isolation qui n&rsquo;existe pas r\u00e9ellement. Un job s&rsquo;ex\u00e9cutant sur un runner auto-h\u00e9berg\u00e9 partag\u00e9 peut \u00eatre en mesure de :<\/p>\n<ul>\n<li>Lire les fichiers laiss\u00e9s par les jobs pr\u00e9c\u00e9dents (identifiants en cache, artefacts de build)<\/li>\n<li>Acc\u00e9der au socket Docker et inspecter ou modifier d&rsquo;autres conteneurs<\/li>\n<li>Atteindre les ressources du r\u00e9seau interne disponibles pour l&rsquo;h\u00f4te du runner<\/li>\n<li>Installer des portes d\u00e9rob\u00e9es persistantes sur le runner pour les jobs futurs<\/li>\n<\/ul>\n<h3>Comptes de service sur-permissionn\u00e9s<\/h3>\n<p>Un pattern d&rsquo;une fr\u00e9quence alarmante consiste \u00e0 donner au compte de service CI\/CD un large acc\u00e8s administratif \u2014 \u00ab juste pour que \u00e7a fonctionne \u00bb. Un r\u00f4le IAM AWS avec <code>AdministratorAccess<\/code>, un compte de service Kubernetes avec <code>cluster-admin<\/code>, ou un compte SQL cloud avec des privil\u00e8ges DBA. Lorsque n&rsquo;importe quelle \u00e9tape du pipeline est compromise, l&rsquo;attaquant h\u00e9rite de toutes ces permissions.<\/p>\n<h3>Confiance implicite dans les actions et templates tiers<\/h3>\n<p>Utiliser des GitHub Actions communautaires ou des templates GitLab CI signifie ex\u00e9cuter le code de quelqu&rsquo;un d&rsquo;autre dans votre pipeline avec vos secrets. Lorsque vous r\u00e9f\u00e9rencez <code>uses: some-org\/some-action@v2<\/code>, vous faites confiance que :<\/p>\n<ul>\n<li>Le code de l&rsquo;action n&rsquo;est pas malveillant<\/li>\n<li>Les mainteneurs de l&rsquo;action n&rsquo;ont pas \u00e9t\u00e9 compromis<\/li>\n<li>Le tag <code>v2<\/code> n&rsquo;a pas \u00e9t\u00e9 d\u00e9plac\u00e9 pour pointer vers un code diff\u00e9rent<\/li>\n<li>Les d\u00e9pendances de l&rsquo;action sont dignes de confiance<\/li>\n<\/ul>\n<p>Les r\u00e9f\u00e9rences de tags sont mutables. Un attaquant qui compromet le d\u00e9p\u00f4t d&rsquo;une action peut d\u00e9placer le tag <code>v2<\/code> vers un commit malveillant, et chaque pipeline r\u00e9f\u00e9ren\u00e7ant ce tag ex\u00e9cutera le nouveau code lors de sa prochaine ex\u00e9cution.<\/p>\n<h3>Confusion entre identit\u00e9 de build et identit\u00e9 de d\u00e9ploiement<\/h3>\n<p>De nombreux pipelines utilisent une seule identit\u00e9 (compte de service, r\u00f4le IAM ou token) pour le build et le d\u00e9ploiement. Cette confusion signifie qu&rsquo;une compromission pendant la phase de build \u2014 qui manipule du code non fiable \u2014 donne un acc\u00e8s direct aux cibles de d\u00e9ploiement. L&rsquo;identit\u00e9 de build ne devrait pouvoir que produire des artefacts. Une identit\u00e9 de d\u00e9ploiement distincte et plus restreinte devrait \u00eatre utilis\u00e9e pour d\u00e9ployer ces artefacts en production.<\/p>\n<h2>Durcissement des hypoth\u00e8ses de confiance<\/h2>\n<p>Avec le mod\u00e8le de menace clarifi\u00e9, voici les mesures d&rsquo;att\u00e9nuation concr\u00e8tes qui alignent les contr\u00f4les sur les fronti\u00e8res de confiance.<\/p>\n<h3>Conditions de d\u00e9clenchement explicites et filtres de branches<\/h3>\n<p>N&rsquo;autorisez jamais les d\u00e9clencheurs de pipeline sans restriction. Limitez les \u00e9v\u00e9nements qui peuvent d\u00e9clencher quels workflows, et assurez-vous que les pipelines privil\u00e9gi\u00e9s ne s&rsquo;ex\u00e9cutent que sur des branches de confiance :<\/p>\n<pre><code># GitHub Actions : restreindre le d\u00e9ploiement \u00e0 la branche main uniquement\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n    # Ne d\u00e9clencher que sur les PRs ciblant main ; le code de la PR s'ex\u00e9cute sans secrets\n\njobs:\n  deploy:\n    if: github.event_name == 'push' && github.ref == 'refs\/heads\/main'\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@v4\n      - run: .\/deploy.sh\n<\/code><\/pre>\n<pre><code># GitLab CI : utiliser des rules pour restreindre les jobs sensibles\ndeploy-production:\n  stage: deploy\n  script:\n    - .\/deploy.sh\n  rules:\n    - if: $CI_COMMIT_BRANCH == \"main\" && $CI_PIPELINE_SOURCE != \"merge_request_event\"\n      when: manual\n      allow_failure: false\n  environment:\n    name: production\n<\/code><\/pre>\n<h3>Permissions minimales des tokens<\/h3>\n<p>Appliquez le principe du moindre privil\u00e8ge \u00e0 chaque token de votre pipeline. Dans GitHub Actions, d\u00e9finissez des permissions par d\u00e9faut restrictives et accordez des permissions sp\u00e9cifiques par job :<\/p>\n<pre><code># D\u00e9finir des valeurs par d\u00e9faut restrictives au niveau du workflow\npermissions: read-all\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      packages: write\n    steps:\n      - uses: actions\/checkout@v4\n      - run: npm ci && npm run build\n\n  deploy:\n    needs: build\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      id-token: write  # Uniquement pour OIDC, pas d'\u00e9criture sur le d\u00e9p\u00f4t\n    environment: production\n    steps:\n      - run: .\/deploy.sh\n<\/code><\/pre>\n<p>Dans GitLab, restreignez la port\u00e9e du <code>CI_JOB_TOKEN<\/code> dans les param\u00e8tres du projet et utilisez exclusivement les variables prot\u00e9g\u00e9es pour les identifiants sensibles.<\/p>\n<h3>Runners \u00e9ph\u00e9m\u00e8res et isol\u00e9s<\/h3>\n<p>Dans la mesure du possible, utilisez des runners \u00e9ph\u00e9m\u00e8res qui sont cr\u00e9\u00e9s \u00e0 neuf pour chaque job et d\u00e9truits imm\u00e9diatement apr\u00e8s. Cela \u00e9limine les attaques bas\u00e9es sur la persistance et les fuites de donn\u00e9es entre jobs. Pour les environnements auto-h\u00e9berg\u00e9s, des outils comme <a href=\"https:\/\/github.com\/actions\/actions-runner-controller\" target=\"_blank\" rel=\"noopener\">Actions Runner Controller<\/a> (ARC) de GitHub pour Kubernetes ou le runner autoscaling de GitLab sur AWS\/GCP peuvent provisionner des pods ou VMs de runner \u00e9ph\u00e9m\u00e8res pour chaque job.<\/p>\n<p>Propri\u00e9t\u00e9s cl\u00e9s d&rsquo;une configuration de runner durcie :<\/p>\n<ul>\n<li>Pas de stockage persistant entre les jobs<\/li>\n<li>Pas de socket Docker partag\u00e9<\/li>\n<li>Segmentation r\u00e9seau limitant l&rsquo;acc\u00e8s aux seuls endpoints requis<\/li>\n<li>Aucune possibilit\u00e9 pour le job de modifier la configuration du runner lui-m\u00eame<\/li>\n<\/ul>\n<h3>\u00c9pinglage des actions et images par SHA<\/h3>\n<p>Les r\u00e9f\u00e9rences mutables (noms de branches, tags comme <code>v2<\/code>) peuvent \u00eatre modifi\u00e9es par les mainteneurs en amont \u2014 ou par des attaquants. L&rsquo;\u00e9pinglage \u00e0 un SHA de commit sp\u00e9cifique garantit que le code exact que vous avez r\u00e9vis\u00e9 est celui qui s&rsquo;ex\u00e9cute dans votre pipeline :<\/p>\n<pre><code># Au lieu de ceci (tag mutable) :\n- uses: actions\/checkout@v4\n\n# Utilisez ceci (SHA immuable) :\n- uses: actions\/checkout@b4ffde65f46336ab88eb53be808477a3936bae11  # v4.1.1\n<\/code><\/pre>\n<p>Le m\u00eame principe s&rsquo;applique aux images de conteneurs. Utilisez les digests d&rsquo;images au lieu des tags :<\/p>\n<pre><code># Au lieu de :\nimage: node:20-alpine\n\n# Utilisez :\nimage: node@sha256:a1b2c3d4e5f6...  # \u00e9pingl\u00e9 \u00e0 un digest sp\u00e9cifique\n<\/code><\/pre>\n<p>Des outils comme Dependabot et Renovate peuvent automatiquement cr\u00e9er des PRs pour mettre \u00e0 jour les SHAs \u00e9pingl\u00e9s lorsque de nouvelles versions sont publi\u00e9es, vous offrant ainsi \u00e0 la fois s\u00e9curit\u00e9 et maintenabilit\u00e9.<\/p>\n<h3>S\u00e9paration des identit\u00e9s de build et de d\u00e9ploiement<\/h3>\n<p>Impl\u00e9mentez des identit\u00e9s distinctes pour les phases de build et de d\u00e9ploiement. L&rsquo;identit\u00e9 de build devrait avoir :<\/p>\n<ul>\n<li>Un acc\u00e8s en lecture au code source<\/li>\n<li>Un acc\u00e8s en \u00e9criture au stockage d&rsquo;artefacts (registre de conteneurs, bucket S3)<\/li>\n<li>Aucun acc\u00e8s aux environnements de production<\/li>\n<\/ul>\n<p>L&rsquo;identit\u00e9 de d\u00e9ploiement devrait avoir :<\/p>\n<ul>\n<li>Un acc\u00e8s en lecture au stockage d&rsquo;artefacts<\/li>\n<li>Un acc\u00e8s en \u00e9criture \u00e0 la cible de d\u00e9ploiement sp\u00e9cifique<\/li>\n<li>Aucun acc\u00e8s au code source ni la capacit\u00e9 de d\u00e9clencher des builds<\/li>\n<\/ul>\n<p>Utilisez la f\u00e9d\u00e9ration OIDC lorsque c&rsquo;est possible pour \u00e9liminer enti\u00e8rement les identifiants \u00e0 longue dur\u00e9e de vie. GitHub Actions et GitLab CI supportent tous deux les tokens OIDC qui peuvent \u00eatre \u00e9chang\u00e9s contre des identifiants de fournisseur cloud \u00e0 courte dur\u00e9e de vie :<\/p>\n<pre><code># GitHub Actions OIDC avec AWS\njobs:\n  deploy:\n    permissions:\n      id-token: write\n      contents: read\n    steps:\n      - uses: aws-actions\/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502\n        with:\n          role-to-assume: arn:aws:iam::123456789012:role\/deploy-production\n          aws-region: us-east-1\n<\/code><\/pre>\n<pre><code># GitLab CI OIDC avec AWS\ndeploy:\n  stage: deploy\n  id_tokens:\n    AWS_TOKEN:\n      aud: https:\/\/gitlab.com\n  script:\n    - >\n      STS_CREDENTIALS=$(aws sts assume-role-with-web-identity\n      --role-arn arn:aws:iam::123456789012:role\/deploy-production\n      --web-identity-token $AWS_TOKEN\n      --role-session-name \"gitlab-ci-${CI_JOB_ID}\")\n    - export AWS_ACCESS_KEY_ID=$(echo $STS_CREDENTIALS | jq -r '.Credentials.AccessKeyId')\n    - .\/deploy.sh\n<\/code><\/pre>\n<h2>Conclusion<\/h2>\n<p>Chaque pipeline CI\/CD poss\u00e8de un mod\u00e8le de confiance. La question est de savoir si ce mod\u00e8le de confiance a \u00e9t\u00e9 con\u00e7u intentionnellement ou s&rsquo;il a \u00e9merg\u00e9 accidentellement des configurations par d\u00e9faut et des corrections rapides.<\/p>\n<p>Le mod\u00e8le d&rsquo;ex\u00e9cution que vous choisissez \u2014 h\u00e9berg\u00e9 en SaaS, auto-h\u00e9berg\u00e9, conteneuris\u00e9 ou serverless \u2014 d\u00e9termine les propri\u00e9t\u00e9s de s\u00e9curit\u00e9 de base de votre pipeline. Mais le mod\u00e8le d&rsquo;ex\u00e9cution seul ne suffit pas. La confiance doit \u00eatre explicitement d\u00e9limit\u00e9e \u00e0 chaque transition : du code source au d\u00e9clencheur, du d\u00e9clencheur \u00e0 l&rsquo;ex\u00e9cution, de l&rsquo;ex\u00e9cution aux secrets, et du build au d\u00e9ploiement.<\/p>\n<p>Les patterns couverts dans ce guide \u2014 Poisoned Pipeline Execution, abus de runners partag\u00e9s, identit\u00e9s sur-permissionn\u00e9es, r\u00e9f\u00e9rences d&rsquo;actions mutables et identit\u00e9s de build\/d\u00e9ploiement confondues \u2014 ne sont pas th\u00e9oriques. Ce sont les techniques r\u00e9ellement utilis\u00e9es dans les attaques de cha\u00eene d&rsquo;approvisionnement du monde r\u00e9el, de la compromission SolarWinds \u00e0 la br\u00e8che Codecov et au-del\u00e0.<\/p>\n<p>Commencez par cartographier vos fronti\u00e8res de confiance actuelles. Identifiez o\u00f9 la confiance est suppos\u00e9e plut\u00f4t que v\u00e9rifi\u00e9e. Puis appliquez les mesures de durcissement de mani\u00e8re syst\u00e9matique : restreignez les d\u00e9clencheurs, minimisez les permissions, isolez les runners, \u00e9pinglez les d\u00e9pendances et s\u00e9parez les identit\u00e9s. Traitez votre pipeline CI\/CD avec la m\u00eame rigueur que vous appliquez \u00e0 votre infrastructure de production \u2014 car en pratique, c&rsquo;est la porte d&rsquo;entr\u00e9e de votre infrastructure de production.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Les pipelines CI\/CD figurent parmi les composants les plus privil\u00e9gi\u00e9s de toute organisation logicielle moderne. Ils clonent le code source, acc\u00e8dent aux secrets, construisent des artefacts et d\u00e9ploient en production \u2014 souvent avec une supervision humaine minimale. Pourtant, malgr\u00e9 ce niveau d&rsquo;acc\u00e8s extraordinaire, les mod\u00e8les de confiance qui sous-tendent ces pipelines sont rarement rendus &#8230; <a title=\"Mod\u00e8les d&rsquo;Ex\u00e9cution CI\/CD et Hypoth\u00e8ses de Confiance : Guide de S\u00e9curit\u00e9\" class=\"read-more\" href=\"https:\/\/secure-pipelines.com\/fr\/ci-cd-security\/ci-cd-execution-models-trust-assumptions-security-guide-2\/\" aria-label=\"En savoir plus sur Mod\u00e8les d&rsquo;Ex\u00e9cution CI\/CD et Hypoth\u00e8ses de Confiance : Guide de S\u00e9curit\u00e9\">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],"tags":[],"post_folder":[],"class_list":["post-485","post","type-post","status-publish","format-standard","hentry","category-ci-cd-security"],"_links":{"self":[{"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/posts\/485","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=485"}],"version-history":[{"count":2,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/posts\/485\/revisions"}],"predecessor-version":[{"id":572,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/posts\/485\/revisions\/572"}],"wp:attachment":[{"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/media?parent=485"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/categories?post=485"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/tags?post=485"},{"taxonomy":"post_folder","embeddable":true,"href":"https:\/\/secure-pipelines.com\/fr\/wp-json\/wp\/v2\/post_folder?post=485"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}