Qu'est-ce que le Top 10 des Risques de Sécurité CI/CD ?

Le Top 10 des Risques de Sécurité CI/CD de l'OWASP identifie les risques de sécurité les plus significatifs dans les pipelines d'Intégration Continue et de Livraison Continue. Les pipelines CI/CD sont des cibles de grande valeur car ils ont un accès direct au code source, aux secrets et aux environnements de production. Ce guide couvre le contrôle des flux, la gestion des identités, les attaques de dépendances, l'empoisonnement de pipelines, et bien plus encore.

1�E�⃣ CICD-SEC-1 - Mécanismes de Contrôle de Flux Insuffisants

Critical

Vue d'ensemble

Les mécanismes de contrôle de flux insuffisants permettent aux attaquants de pousser du code malveillant à travers les pipelines CI/CD sans examen ni porte d'approbation appropriés. Cela inclut le contournement des règles de protection de branches, l'absence d'approbations requises et le manque d'application des contrôles sur qui peut déclencher des déploiements en production.

Risque

Sans contrôle de flux approprié, un seul compte développeur compromis ou un initié malveillant peut pousser du code directement en production, contournant la revue de code, les analyses de sécurité et les processus d'approbation. Cela peut conduire au déploiement de portes dérobées, de code d'exfiltration de données ou de charges utiles destructives.

Exemple de Code Vulnérable

YAML (GitHub Actions) ❁EMauvais
# No branch protection  Eanyone can push directly to main
name: Deploy
on:
  push:
    branches: [main]  # Triggers on any push to main
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: |
        # Deploys immediately  Eno approval gate!
        kubectl apply -f deploy.yaml
        kubectl rollout status deployment/myapp

Exemple de Code Sécurisé

YAML (GitHub Actions) ✁EBon
name: Deploy
on:
  push:
    branches: [main]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: npm test
  deploy:
    needs: test
    runs-on: ubuntu-latest
    environment: production  # Requires manual approval
    steps:
    - uses: actions/checkout@v4
    - run: |
        kubectl apply -f deploy.yaml
        kubectl rollout status deployment/myapp

Liste de Contrôle d'Atténuation

2�E�⃣ CICD-SEC-2 - Gestion Inadéquate des Identités et des Accès

Critical

Vue d'ensemble

Les systèmes CI/CD impliquent de multiples identités : utilisateurs humains, comptes de service, jetons de bot et identités machine. Une gestion IAM inadéquate permet un accès trop permissif aux dépôts, pipelines et cibles de déploiement. Les identifiants partagés, les comptes obsolètes et l'absence de MFA aggravent le risque.

Risque

Des identités CI/CD compromises avec des permissions excessives peuvent modifier les pipelines, accéder aux secrets, altérer les artefacts de build et déployer en production. Les comptes de service partagés rendent impossible l'audit de qui a effectué une action.

Exemple de Code Vulnérable

YAML (GitHub Actions) ❁EMauvais
# Over-permissive workflow with admin token
name: CI
on: push
permissions: write-all  # Full permissions to everything!
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: |
        # Using org-wide PAT with admin access
        curl -H "Authorization: token ${{ secrets.ADMIN_PAT }}" \
          https://api.github.com/repos/org/other-repo/contents/

Exemple de Code Sécurisé

YAML (GitHub Actions) ✁EBon
name: CI
on: push
permissions:
  contents: read    # Minimum required permissions
  packages: write   # Only what's needed
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: actions/create-github-app-token@v1  # Scoped app token
      id: app-token
      with:
        app-id: ${{ vars.APP_ID }}
        private-key: ${{ secrets.APP_PRIVATE_KEY }}
        repositories: other-repo  # Scoped to specific repo

Liste de Contrôle d'Atténuation

3�E�⃣ CICD-SEC-3 - Abus de la Chaîne de Dépendances

Critical

Vue d'ensemble

Les pipelines CI/CD récupèrent des dépendances depuis des registres de packages externes (npm, PyPI, Maven, Docker Hub). Les attaquants exploitent cela par la confusion de dépendances, le typosquatting, la compromission de comptes de mainteneurs et les packages malveillants. Une seule dépendance empoisonnée peut exécuter du code arbitraire pendant le build.

Risque

Les dépendances malveillantes exécutent du code lors de l'installation (scripts postinstall, setup.py), volant des secrets, injectant des portes dérobées dans les artefacts de build ou établissant une persistance. Les attaques de la chaîne d'approvisionnement comme SolarWinds et Codecov démontrent l'impact catastrophique.

Exemple de Code Vulnérable

Jenkinsfile ❁EMauvais
pipeline {
  agent any
  stages {
    stage('Build') {
      steps {
        // No lockfile verification, no integrity checks
        sh 'npm install'           // Fetches latest  Ecould be compromised!
        sh 'pip install -r requirements.txt'  // No hash verification
      }
    }
  }
}

Exemple de Code Sécurisé

Jenkinsfile ✁EBon
pipeline {
  agent any
  stages {
    stage('Build') {
      steps {
        // Use lockfile with integrity verification
        sh 'npm ci'                   // Uses package-lock.json
        sh 'npm audit --audit-level=high'
        // Python: verify hashes from lockfile
        sh 'pip install --require-hashes -r requirements.lock'
      }
    }
    stage('SCA Scan') {
      steps {
        // Software Composition Analysis
        sh 'trivy fs --scanners vuln,secret .'
      }
    }
  }
}

Liste de Contrôle d'Atténuation

4�E�⃣ CICD-SEC-4 - Exécution de Pipeline Empoisonnée (PPE)

Critical

Vue d'ensemble

L'Exécution de Pipeline Empoisonnée (PPE) se produit lorsque des attaquants peuvent modifier les définitions de pipeline CI/CD ou injecter du code malveillant qui s'exécute dans le contexte du pipeline. Cela peut se produire par la manipulation de fichiers de configuration de pipeline dans des branches, des pull requests depuis des forks ou la modification de modèles de pipeline partagés.

Risque

Un attaquant qui peut modifier la configuration du pipeline obtient l'accès à tous les secrets, identifiants et permissions disponibles pour le pipeline. Il peut exfiltrer des secrets, altérer les résultats de build ou déployer du code malveillant  Ele tout dans un contexte d'exécution de confiance.

Exemple de Code Vulnérable

YAML (GitHub Actions) ❁EMauvais
# Runs pipeline from fork PRs with access to secrets
name: CI
on:
  pull_request_target:  # Runs in base repo context with secrets!
    branches: [main]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
      with:
        ref: ${{ github.event.pull_request.head.sha }}  # Checks out fork code!
    - run: make build  # Fork's Makefile executes with secrets access
      env:
        DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}

Exemple de Code Sécurisé

YAML (GitHub Actions) ✁EBon
# Separate workflows: untrusted build + trusted deploy
name: CI
on:
  pull_request:  # No secret access for PR builds
    branches: [main]
permissions:
  contents: read
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4  # Checks out merge commit (safe)
    - run: npm ci && npm test   # No secrets needed for build/test
    - uses: actions/upload-artifact@v4
      with:
        name: build-output
        path: dist/

Liste de Contrôle d'Atténuation

5�E�⃣ CICD-SEC-5 - Contrôles d'Accès Basés sur le Pipeline (PBAC) Insuffisants

High

Vue d'ensemble

Les Contrôles d'Accès Basés sur le Pipeline (PBAC) régissent les ressources auxquelles un pipeline peut accéder : comptes cloud, clusters Kubernetes, bases de données et services internes. Un PBAC insuffisant signifie que les pipelines ont un accès plus large que nécessaire, violant le principe du moindre privilège.

Risque

Les pipelines sur-privilégiés peuvent être exploités pour accéder à des ressources bien au-delà de leur portée prévue. Un pipeline de build compromis pour un service mineur pourrait être utilisé pour accéder aux bases de données de production, modifier l'infrastructure ou pivoter vers d'autres environnements.

Exemple de Code Vulnérable

YAML (GitLab CI) ❁EMauvais
# Pipeline with admin-level cloud credentials
deploy:
  stage: deploy
  script:
    - aws configure set aws_access_key_id $AWS_ACCESS_KEY
    - aws configure set aws_secret_access_key $AWS_SECRET_KEY
    # This key has AdministratorAccess policy!
    - aws s3 sync dist/ s3://my-bucket/
    - aws ecs update-service --cluster prod --service myapp
    # Same credentials could access ANY AWS resource

Exemple de Code Sécurisé

YAML (GitHub Actions) ✁EBon
name: Deploy
on:
  push:
    branches: [main]
permissions:
  id-token: write  # For OIDC
  contents: read
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: aws-actions/configure-aws-credentials@v4
      with:
        role-to-assume: arn:aws:iam::123456:role/deploy-s3-only
        # Scoped role: only s3:PutObject on specific bucket
        aws-region: us-east-1
    - run: aws s3 sync dist/ s3://my-bucket/

Liste de Contrôle d'Atténuation

6�E�⃣ CICD-SEC-6 - Hygiène des Identifiants Insuffisante

Critical

Vue d'ensemble

Les pipelines CI/CD gèrent de nombreux identifiants : clés API, jetons cloud, mots de passe de registre, clés SSH et certificats de signature. Une mauvaise hygiène des identifiants inclut le codage en dur de secrets dans les fichiers de pipeline, l'affichage de secrets dans les journaux, l'utilisation de stockage de secrets non chiffré et l'absence de rotation des identifiants.

Risque

Les identifiants CI/CD divulgués sont l'un des vecteurs d'accès initial les plus courants. Les secrets exposés dans les journaux de build, commités dans les dépôts ou stockés sans chiffrement fournissent aux attaquants un accès direct aux systèmes de production, comptes cloud et registres d'artefacts.

Exemple de Code Vulnérable

Bash (CI Script) ❁EMauvais
#!/bin/bash
# Secrets hardcoded and leaked in logs
export DOCKER_PASSWORD="MyS3cret!"         # Hardcoded!
echo "Logging in with $DOCKER_PASSWORD"  # Printed to logs!

docker login -u admin -p "$DOCKER_PASSWORD" registry.example.com
docker push registry.example.com/myapp:latest

# AWS credentials in environment  Evisible in process listing
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCY"
aws s3 cp artifact.zip s3://releases/

Exemple de Code Sécurisé

YAML (GitHub Actions) ✁EBon
name: Publish
on:
  push:
    tags: ['v*']
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: docker/login-action@v3  # Handles credentials securely
      with:
        registry: registry.example.com
        username: ${{ secrets.DOCKER_USER }}   # Masked in logs
        password: ${{ secrets.DOCKER_TOKEN }}  # Short-lived token
    - run: |
        docker build -t registry.example.com/myapp:${{ github.ref_name }} .
        docker push registry.example.com/myapp:${{ github.ref_name }}

Liste de Contrôle d'Atténuation

7�E�⃣ CICD-SEC-7 - Configuration Système Insécurisée

High

Vue d'ensemble

Les systèmes CI/CD (Jenkins, GitLab, runners GitHub Actions) fonctionnent souvent avec des configurations par défaut insécurisées. Cela inclut des versions logicielles obsolètes, des interfaces de gestion exposées, des fonctionnalités de sécurité désactivées, un accès réseau trop permissif et des runners auto-hébergés partagés entre projets.

Risque

Une infrastructure CI/CD mal configurée peut être exploitée pour obtenir un accès non autorisé aux environnements de build, intercepter des secrets ou pivoter vers des réseaux internes. Les runners auto-hébergés partagés permettent des attaques inter-projets où un workflow compromis affecte les autres.

Exemple de Code Vulnérable

Groovy (Jenkins) ❁EMauvais
// Jenkins with insecure configuration
// - Script console enabled without auth
// - Agent-to-controller access unrestricted
// - Outdated plugins with known CVEs

pipeline {
  agent any  // Runs on any available agent  Eno isolation
  stages {
    stage('Build') {
      steps {
        // Running as root on shared agent
        sh 'whoami'  // root
        sh 'docker build -t myapp .'
      }
    }
  }
}

Exemple de Code Sécurisé

Groovy (Jenkins) ✁EBon
pipeline {
  agent {
    kubernetes {  // Ephemeral, isolated pod per build
      yaml """
        apiVersion: v1
        kind: Pod
        spec:
          securityContext:
            runAsNonRoot: true
            runAsUser: 1000
          containers:
          - name: builder
            image: builder:1.2.3
            securityContext:
              allowPrivilegeEscalation: false
              readOnlyRootFilesystem: true
      """
    }
  }
  stages {
    stage('Build') {
      steps {
        container('builder') {
          sh 'make build'
        }
      }
    }
  }
}

Liste de Contrôle d'Atténuation

8�E�⃣ CICD-SEC-8 - Utilisation Non Gouvernée de Services Tiers

High

Vue d'ensemble

Les pipelines CI/CD s'intègrent souvent avec des services tiers : outils de qualité de code, scanners de sécurité, systèmes de notification et plateformes de déploiement. Ces intégrations reçoivent des jetons d'accès et des permissions, créant une chaîne de confiance. L'utilisation non gouvernée signifie aucune visibilité sur ce que les services tiers peuvent accéder ou faire.

Risque

Un service tiers compromis (comme la brèche Codecov) peut accéder au code source, aux secrets et aux artefacts de build. Sans gouvernance, les équipes peuvent accorder des permissions excessives à des services inconnus, créant des vecteurs d'attaque invisibles dans la chaîne d'approvisionnement.

Exemple de Code Vulnérable

YAML (GitHub Actions) ❁EMauvais
name: CI
on: push
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: npm test
    # Unknown third-party action with full repo access
    - uses: random-org/code-analysis@main  # Unpinned, unvetted!
      with:
        token: ${{ secrets.GITHUB_TOKEN }}   # Full token access!
    # Uploading coverage to external service with repo token
    - run: |
        bash <(curl -s https://example.com/uploader.sh)  # Remote script!

Exemple de Code Sécurisé

YAML (GitHub Actions) ✁EBon
name: CI
on: push
permissions:
  contents: read
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: npm test
    # Vetted action pinned to SHA
    - uses: github/codeql-action/analyze@8a470fddafa5cbc14  # Pinned SHA
    # Upload via official CLI tool, not remote scripts
    - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673
      with:
        token: ${{ secrets.CODECOV_TOKEN }}  # Scoped token
        fail_ci_if_error: true

Liste de Contrôle d'Atténuation

9�E�⃣ CICD-SEC-9 - Validation de l'Intégrité des Artefacts Inadéquate

High

Vue d'ensemble

Les artefacts de build (images de conteneurs, binaires, packages) transitent par les pipelines CI/CD vers la production. Sans validation d'intégrité, les artefacts peuvent être altérés à n'importe quel point : pendant le build, en transit, dans le registre d'artefacts ou au moment du déploiement. Cela brise la chaîne de confiance du code à la production.

Risque

Les artefacts altérés peuvent contenir des portes dérobées, des logiciels malveillants ou une logique modifiée. Sans signature et vérification, il n'y a aucun moyen de détecter si un artefact a été modifié après le build. Les attaquants peuvent remplacer des images légitimes dans les registres ou intercepter des artefacts en transit.

Exemple de Code Vulnérable

Bash ❁EMauvais
#!/bin/bash
# Build and deploy without any integrity checks
docker build -t myregistry.com/app:latest .
docker push myregistry.com/app:latest

# On deployment side  Eno verification
docker pull myregistry.com/app:latest  # Could be tampered!
docker run myregistry.com/app:latest   # Tag is mutable!

Exemple de Code Sécurisé

YAML (GitHub Actions) ✁EBon
name: Build and Sign
on:
  push:
    tags: ['v*']
permissions:
  id-token: write
  packages: write
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: |
        # Build with immutable tag (SHA)
        docker build -t myregistry.com/app:${{ github.sha }} .
        docker push myregistry.com/app:${{ github.sha }}
    - uses: sigstore/cosign-installer@v3
    - run: |
        # Sign image with keyless signing (Sigstore)
        cosign sign myregistry.com/app:${{ github.sha }}
        # Generate and attach SBOM
        syft myregistry.com/app:${{ github.sha }} -o spdx-json > sbom.json
        cosign attest --predicate sbom.json myregistry.com/app:${{ github.sha }}

Liste de Contrôle d'Atténuation

🔟 CICD-SEC-10 - Journalisation et Visibilité Insuffisantes

Medium

Vue d'ensemble

Les environnements CI/CD génèrent des événements de sécurité critiques : exécutions de pipelines, changements de configuration, accès aux secrets et activités de déploiement. Sans journalisation et surveillance complètes, les activités malveillantes dans le pipeline passent inaperçues et la réponse aux incidents est sévèrement entravée.

Risque

Sans visibilité sur les activités CI/CD, les attaquants peuvent modifier les pipelines, exfiltrer des secrets et altérer des artefacts sans déclencher d'alertes. L'absence de pistes d'audit rend impossible la détermination de la portée et de l'impact d'une violation.

Exemple de Code Vulnérable

Bash ❁EMauvais
#!/bin/bash
# Pipeline with no logging or audit trail
echo "Starting deployment..."
kubectl apply -f deploy.yaml
echo "Done."

# No record of: who triggered this, what changed,
# which image was deployed, what secrets were accessed
# Build logs expire after 30 days with no archival

Exemple de Code Sécurisé

YAML (GitHub Actions) ✁EBon
name: Audited Deploy
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - name: Log deployment metadata
      run: |
        echo "=== Deployment Audit Log ==="
        echo "Triggered by: ${{ github.actor }}"
        echo "Commit: ${{ github.sha }}"
        echo "Ref: ${{ github.ref }}"
        echo "Workflow: ${{ github.workflow }}"
        echo "Run ID: ${{ github.run_id }}"
    - name: Deploy with audit
      run: |
        kubectl apply -f deploy.yaml 2>&1 | tee deploy.log
        # Send audit event to SIEM
        curl -X POST "${{ secrets.SIEM_WEBHOOK }}" \
          -d '{"event":"deploy","actor":"${{ github.actor }}","sha":"${{ github.sha }}"}'

Liste de Contrôle d'Atténuation

📊 Tableau Récapitulatif

ID Vulnérabilité Sévérité Atténuation Clé
CICD-SEC-1Mécanismes de Contrôle de Flux InsuffisantsCriticalProtection de branches, approbations requises, portes d'environnement
CICD-SEC-2Gestion Inadéquate des Identités et des AccèsCriticalJetons au moindre privilège, OIDC, MFA, rotation des identifiants
CICD-SEC-3Abus de la Chaîne de DépendancesCriticalFichiers de verrouillage, vérification de hachage, registres privés, SCA
CICD-SEC-4Exécution de Pipeline Empoisonnée (PPE)CriticalSéparer build/déploiement, définitions de pipeline immuables, contrôles de forks
CICD-SEC-5PBAC InsuffisantHighFédération OIDC, rôles IAM ciblés, séparation des environnements
CICD-SEC-6Hygiène des Identifiants InsuffisanteCriticalGestion des secrets, masquage des journaux, rotation, analyse de secrets
CICD-SEC-7Configuration Système InsécuriséeHighRunners éphémères, non-root, mise à jour des plugins, isolation réseau
CICD-SEC-8Utilisation Non Gouvernée de Services TiersHighInventaire des services, épinglage SHA, pas de scripts distants
CICD-SEC-9Validation de l'Intégrité des Artefacts InadéquateHighSignature Cosign, contrôle d'admission, provenance SLSA
CICD-SEC-10Journalisation et Visibilité InsuffisantesMediumJournalisation d'audit, intégration SIEM, alertes, rétention des journaux