MDstable
NoteSnippetChecklistPlaybook

DevSecOps — Sécurité dans les pipelines CI/CD

Intégration de la sécurité dans les pipelines CI/CD : SAST, DAST, SCA, secret scanning, container scanning avec GitHub Actions et GitLab CI

snippetintermediate 2026-05-30 4 min read
devsecopscicdsastdastscagithub-actionsgitlab-cisecurity

Principe Shift-Left

Traditionnel Dveloppement Test Staging Production Audit scu
Shift-Left Scu Scu Scu Scu 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 > secretsbaseline
detect-secrets audit secretsbaseline
# Hook Git
cat > git/hooks/pre-commit << 'EOF'
detect-secrets-hook --baseline secretsbaseline
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/etcro -v /var/varro
aquasec/kube-benchlatest
# 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 |

OPS·BRAIN v1.05 notes · DevOpslocal