---
title: "DevSecOps — Sécurité dans les pipelines CI/CD"
domain: devops
subdomain: cicd
type: snippet
tags: [devsecops, cicd, sast, dast, sca, github-actions, gitlab-ci, security]
difficulty: intermediate
status: stable
updated: "Sat May 30 2026 00:00:00 GMT+0000 (Coordinated Universal Time)"
---
## Principe Shift-Left

```
Traditionnel : Développement → Test → Staging → Production → [Audit sécu]
Shift-Left   : [Sécu] → [Sécu] → [Sécu] → [Sécu] → Production
               IDE       Commit   CI/CD    Release
```

### Outils par phase

| Phase | Outil | Type |
|-------|-------|------|
| IDE | SonarLint, Snyk IDE | SAST temps réel |
| Pre-commit | detect-secrets, gitleaks | Secret scanning |
| CI — Build | SonarQube, Bandit, Semgrep | SAST |
| CI — Dépendances | OWASP Dependency-Check, Snyk | SCA |
| CI — Container | Trivy, Grype, Syft | Container scan |
| CD — Deploy | OWASP ZAP, Nuclei | DAST |
| Runtime | Falco, Wazuh | RASP / monitoring |

---

## GitHub Actions — Pipeline complet

```yaml
# .github/workflows/devsecops.yml
name: DevSecOps Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:

jobs:
  # ─── 1. Secret scanning ───────────────────────────────
  secret-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Historique complet pour Gitleaks

      - name: Gitleaks — scan secrets
        uses: gitleaks/gitleaks-action@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  # ─── 2. SAST — Analyse statique ───────────────────────
  sast:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Semgrep SAST
        uses: semgrep/semgrep-action@v1
        with:
          config: >-
            p/security-audit
            p/owasp-top-ten
            p/python
        env:
          SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}

      - name: Bandit (Python)
        run: |
          pip install bandit
          bandit -r . -f json -o bandit-report.json || true

      - name: Upload SAST results
        uses: actions/upload-artifact@v4
        with:
          name: sast-reports
          path: "*.json"

  # ─── 3. SCA — Dépendances vulnérables ─────────────────
  dependency-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: OWASP Dependency-Check
        uses: dependency-check/Dependency-Check_Action@main
        with:
          project: 'MonApp'
          path: '.'
          format: 'HTML'
          out: 'reports'

      - name: Snyk — Scan dépendances
        uses: snyk/actions/python@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          args: --severity-threshold=high

  # ─── 4. Container scanning ────────────────────────────
  container-scan:
    runs-on: ubuntu-latest
    needs: [sast]
    steps:
      - uses: actions/checkout@v4

      - name: Build image
        run: docker build -t app:${{ github.sha }} .

      - name: Trivy — scan image
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'app:${{ github.sha }}'
          format: 'sarif'
          output: 'trivy-results.sarif'
          severity: 'CRITICAL,HIGH'
          exit-code: '1'

      - name: Upload Trivy results
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: trivy-results.sarif

  # ─── 5. DAST — Test dynamique (staging) ───────────────
  dast:
    runs-on: ubuntu-latest
    needs: [container-scan]
    if: github.ref == 'refs/heads/main'
    steps:
      - name: Start app
        run: docker run -d -p 8080:8080 app:${{ github.sha }}

      - name: OWASP ZAP Baseline Scan
        uses: zaproxy/action-baseline@v0.9.0
        with:
          target: 'http://localhost:8080'
          fail_action: false
          artifact_name: 'zap-report'
```

---

## GitLab CI — Pipeline équivalent

```yaml
# .gitlab-ci.yml
stages:
  - secret-scan
  - sast
  - dependency-check
  - build
  - container-scan
  - dast

variables:
  DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

secret-scan:
  stage: secret-scan
  image: zricethezav/gitleaks:latest
  script:
    - gitleaks detect --source . --exit-code 1

semgrep:
  stage: sast
  image: returntocorp/semgrep:latest
  script:
    - semgrep --config=p/owasp-top-ten --json > semgrep-report.json
  artifacts:
    reports:
      sast: semgrep-report.json

dependency-check:
  stage: dependency-check
  image: owasp/dependency-check:latest
  script:
    - /usr/share/dependency-check/bin/dependency-check.sh
        --project "MonApp" --scan . --format HTML --out reports/
  artifacts:
    paths: [reports/]

trivy-scan:
  stage: container-scan
  image: aquasec/trivy:latest
  script:
    - trivy image --exit-code 1 --severity CRITICAL,HIGH $DOCKER_IMAGE

owasp-zap:
  stage: dast
  image: ghcr.io/zaproxy/zaproxy:stable
  script:
    - zap-baseline.py -t http://staging.target.com -r zap-report.html
  artifacts:
    paths: [zap-report.html]
  only:
    - main
```

---

## Secret Scanning — Configuration

```bash
# Gitleaks — config .gitleaks.toml
[allowlist]
  description = "Allowed secrets"
  regexes = [
    '''EXAMPLE_API_KEY_[A-Z0-9]{20}''',  # Clés de test
  ]
  paths = [
    '''tests/fixtures/''',
  ]

# Pre-commit hook local
pip install detect-secrets
detect-secrets scan > .secrets.baseline
detect-secrets audit .secrets.baseline

# Hook Git
cat > .git/hooks/pre-commit << 'EOF'
detect-secrets-hook --baseline .secrets.baseline
EOF
chmod +x .git/hooks/pre-commit
```

---

## SonarQube — Quality Gate DevSecOps

```yaml
# docker-compose.yml SonarQube
services:
  sonarqube:
    image: sonarqube:community
    ports:
      - "9000:9000"
    environment:
      - SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true
    volumes:
      - sonar_data:/opt/sonarqube/data
      - sonar_logs:/opt/sonarqube/logs

# sonar-project.properties
sonar.projectKey=mon-projet
sonar.sources=src
sonar.tests=tests
sonar.python.coverage.reportPaths=coverage.xml

# Quality Gate — seuils recommandés
# Security Rating : A (0 vulnérabilités)
# Reliability Rating : A (0 bugs bloquants)
# Maintainability Rating : A
# Coverage : > 80%
# Duplicated Lines : < 3%
```

---

## Infrastructure as Code — Sécurité

```bash
# Checkov — scan Terraform/Kubernetes/Dockerfile
pip install checkov
checkov -d . --framework terraform
checkov -d . --framework kubernetes
checkov -f Dockerfile

# tfsec — Terraform security scanner
tfsec .

# kube-bench — CIS Benchmark Kubernetes
docker run --pid=host -v /etc:/etc:ro -v /var:/var:ro \
  aquasec/kube-bench:latest

# hadolint — Dockerfile linter
hadolint Dockerfile
```

---

## Métriques DevSecOps

| Métrique | Cible | Mesure |
|----------|-------|--------|
| MTTF (Mean Time To Fix) | < 5 jours (High) | Ticket JIRA → merge |
| Vulnérabilités critiques en prod | 0 | Trivy + Dependabot |
| Couverture SAST | > 90% du code | SonarQube |
| Secrets en clair commités | 0 | Gitleaks alertes |
| Score sécurité image Docker | A | Trivy |
