Aller au contenu principal
own2pwn
DevSecOps : intégrer SAST et DAST dans sa CI/CD (GitHub, GitLab)

DevSecOps : intégrer SAST et DAST dans sa CI/CD (GitHub, GitLab)

Où placer le SAST (sur la PR) et le DAST (en staging), comment brancher SARIF sur GitHub Code Scanning et GitLab, et écrire un security gate qui bloque sans noyer les devs.

own2pwn8 min de lectureMis à jour le

SAST et DAST dans la CI/CD, sans le bruit

SecAI s'intègre au pipeline et trie l'exploitable du faux positif par l'IA.

Industrialiser mon AppSec

Vous connaissez la scène. Une faille passe en prod. La rétro commence, et quelqu'un finit par lâcher la phrase magique : "on aurait dû scanner ça avant". Bien sûr qu'on aurait dû. Le problème, ce n'est presque jamais l'absence d'outils, c'est qu'ils tournent à côté du pipeline, dans un onglet que plus personne n'ouvre, au lieu de tourner dans le pipeline, là où ils peuvent réellement arrêter un déploiement.

Intégrer du SAST et du DAST dans sa CI/CD, ce n'est pas "ajouter une étape qui crache un rapport". C'est répondre à trois questions précises : à quel moment chaque outil tourne, où atterrissent les résultats, et qu'est-ce qui décide de casser le build. On va répondre aux trois, avec du YAML qui existe vraiment et zéro flag inventé.

Drake refuse de scanner uniquement en local, approuve de scanner dans la CI
Le scanner sur votre laptop ne protège que votre laptop.

Le principe : shift-left, mais pas que

Le shift-left, c'est l'idée de pousser la sécurité le plus tôt possible dans le cycle de dev, sur le commit, sur la PR, avant que le code n'atteigne un environnement. Plus une faille est détectée tôt, moins elle coûte cher à corriger. C'est vrai, c'est documenté, et le secteur l'a largement adopté : selon Checkmarx, l'intégration du SAST directement dans les outils CI/CD existants des développeurs est aujourd'hui la norme.

Mais "shift-left" ne veut pas dire "tout à gauche". Le SAST se déplace à gauche parce qu'il lit du code source, il n'a besoin de rien qui tourne. Le DAST, lui, a besoin d'une application déployée et fonctionnelle pour l'attaquer. Le coller sur chaque PR n'a tout simplement pas de sens. La bonne mentalité, c'est shift-left ce qui peut l'être, shift-right le reste.

La règle de placement, en une phrase

SAST = sur la PR (boîte blanche, instantané). DAST = en staging après déploiement (boîte noire, a besoin d'une appli qui tourne). Tout le reste découle de ça.

Où placer chaque outil dans le pipeline

Un pipeline CI/CD bien réglé : chaque commit passe sur la chaîne, contrôles de sécurité inclus.

Voici la topologie qui marche dans la vraie vie. Le SAST et les scans rapides (secrets, SCA) tournent tôt et bloquent la PR ; le DAST tourne après déploiement en staging, déclenché par le déploiement lui-même.

pipeline
Commit ou pull request
Contrôles rapides, avant le merge
  1. Un scan de secrets s'exécute en premier, et il est rapide.
  2. Un scan SCA passe ensuite les dépendances en revue, rapide lui aussi.
  3. Un SAST analyse enfin le code source, en boîte blanche.
  4. Le gate de sécurité tranche : en présence d'un finding high ou critical, la pull request échoue et le merge est bloqué ; sinon le merge est autorisé.
Merge puis déploiement en staging
Contrôles sur l'application qui tourne
  1. L'application est déployée en staging.
  2. Un scan DAST est lancé contre cette application qui tourne.
  3. Le gate de sécurité tranche à nouveau : en présence d'un finding high ou critical, la promotion en production est bloquée ; sinon elle est autorisée.
SAST, secrets et SCA bloquent la pull request. Le DAST tourne en staging, après déploiement.

Notez qu'on ne lance pas le DAST sur chaque commit : c'est lent et ça exige une appli déployée. Snyk recommande une approche en couches : scans légers et ciblés au fil de l'eau, un DAST complet déclenché à chaque déploiement en staging, et un scan exhaustif planifié la nuit ou le week-end. Vous avez ainsi du feedback rapide sans transformer chaque push en pause café de quarante minutes.

Pourquoi pas tout en une seule étape ?

Parce que chaque outil regarde une chose différente, à un moment différent. Empiler les couches, c'est précisément ce qui réduit le bruit : croiser un finding SAST ("cette fonction est vulnérable") avec un finding DAST ("et elle est réellement exploitable en runtime") vous dit lesquelles corriger en premier. Un détail seul ment souvent ; deux détails qui concordent, beaucoup moins.

Brancher les résultats : SARIF + GitHub Code Scanning

Le piège classique : chaque outil a son propre format de rapport, et vous finissez avec quatre dashboards que personne ne consulte. La réponse s'appelle SARIF (Static Analysis Results Interchange Format), un format JSON standardisé que la plupart des scanners savent exporter. L'intérêt : un format unique que votre plateforme sait afficher au bon endroit.

Sur GitHub, ce bon endroit, c'est Code Scanning. Vous uploadez le SARIF, et les findings apparaissent directement dans l'onglet Security et en annotations sur la PR, là où le dev les voit sans changer de fenêtre. Voici l'étape officielle, telle qu'elle figure dans la documentation GitHub :

yaml
name: "Security scan"

on:
  pull_request:
  push:
    branches: [main]

jobs:
  sast:
    runs-on: ubuntu-latest
    permissions:
      security-events: write   # obligatoire pour publier dans Code Scanning
      actions: read
      contents: read
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6

      # ... ici votre scanner SAST qui produit un fichier results.sarif ...

      - name: Upload SARIF file
        uses: github/codeql-action/upload-sarif@v4
        with:
          sarif_file: results.sarif
          category: my-analysis-tool

Le piège des permissions

Sans security-events: write, l'upload SARIF échoue silencieusement ou en 403, et vous passez l'après-midi à vous demander pourquoi l'onglet Security reste vide. C'est la première chose à vérifier.

Le paramètre category permet de distinguer plusieurs outils sur un même commit (un pour le SAST, un pour le SCA, etc.) sans que les résultats s'écrasent entre eux.

GitLab SAST : activer, lire le rapport, bloquer la MR

Sur GitLab, l'activation du SAST tient en une inclusion de template dans le .gitlab-ci.yml. D'après la documentation GitLab, on ajoute :

yaml
include:
  - template: Jobs/SAST.gitlab-ci.yml

# Variante en composant CI/CD :
# include:
#   - component: gitlab.com/components/sast/sast@main

Chaque analyseur SAST produit un artefact JSON, gl-sast-report.json. Les résultats remontent dans le widget de la merge request, qui affiche les vulnérabilités nouvellement introduites ou résolues par la branche ; sur GitLab Ultimate, les lignes concernées sont aussi marquées dans la vue des modifications.

Le SAST ne bloque pas la MR tout seul

Point souvent mal compris : le job SAST réussit même quand il trouve des vulnérabilités. Empêcher la fusion sur ces findings n'est pas le comportement par défaut. Il faut une politique dédiée (scan result policy ou merge request approval policy sur GitLab Ultimate), ou un job de gate maison qui échoue sur un seuil de sévérité, comme l'exemple GitLab CI plus bas.

Le security gate : où l'on décide de casser le build

On arrive au cœur du sujet. Un scan qui ne bloque jamais rien, c'est de la décoration. Le security gate (porte de sécurité), c'est la règle qui décide : ce finding fait-il échouer le pipeline, oui ou non ? Et c'est là que se joue toute la crédibilité de votre démarche.

Gandalf bloquant le passage, métaphore du security gate qui bloque la PR
Le security gate face à une PR qui embarque un secret hardcodé et trois injections SQL.

La tentation du débutant : "on bloque sur tout". Résultat, la première PR échoue sur 4 000 findings dont 3 800 faux positifs, l'équipe désactive le gate dans la semaine, et vous voilà revenu au point de départ, sauf que maintenant tout le monde déteste la sécurité. Snyk le dit sans détour : il faut définir des seuils de sévérité clairs pour les échecs de build, en ne bloquant que sur le high et le critical, pour équilibrer sécurité et vélocité.

yaml
# Exemple GitLab CI : le gate ne casse le build que sur high/critical
sast_gate:
  stage: test
  script:
    - python check_findings.py report.sarif --fail-on high,critical
  # les findings low/medium sont remontés en rapport, sans bloquer
  allow_failure: false

dast:
  stage: deploy
  script:
    - run-dast --target https://staging.example.com --report dast.sarif
  rules:
    - if: '$CI_COMMIT_BRANCH == "staging"'   # DAST uniquement en staging

La logique du gate "adulte" tient en quelques principes :

  • Bloquer sur high/critical, remonter le reste. Les findings low/medium apparaissent dans le rapport et l'onglet Security, mais ne cassent pas le build. On les traite, on ne les ignore pas, mais ils n'ont pas droit de veto sur chaque PR.
  • Bloquer dur sur les secrets. Une clé API ou un mot de passe committé, c'est un échec immédiat, sévérité ou pas. Le coût d'une fuite de secret dépasse toujours le coût d'un build cassé.
  • Gérer les faux positifs proprement. Un fichier d'exceptions versionné (baseline / suppressions) plutôt qu'un gate désactivé. La différence entre une équipe mature et une équipe qui a juré sur la sécurité, c'est l'existence de ce fichier.
  • Différencier PR et déploiement. Le gate SAST bloque le merge ; le gate DAST bloque la promotion vers la prod. Deux portes, deux moments.

Roll safe

Can't break prod if the gate blocks the PR. C'est bête, c'est vrai, et c'est exactement pour ça qu'on met le gate avant le merge plutôt qu'après le déploiement.

Ne pas noyer les devs (sinon tout s'effondre)

Le plus gros risque d'un pipeline DevSecOps, ce n'est pas la faille qu'il rate. C'est l'alert fatigue : le moment où l'équipe arrête de lire les alertes parce qu'il y en a trop, et où elle finit par tout ignorer en bloc, y compris les vraies. Un scanner qui crie tout le temps, c'est un détecteur de fumée qu'on débranche.

Le chien dans la pièce en feu, le build passe au vert quand même
Build au vert, 4 000 alertes ignorées, deux failles critiques en prod. This is fine.

Quelques garde-fous concrets contre le bruit :

  • Commencer petit. Le pattern recommandé par le secteur : d'abord le SAST sur les PR, puis le SCA/SBOM sur les builds, puis le DAST en staging. On ajoute une couche quand la précédente est sous contrôle, pas toutes le même jour.
  • Tuner pour votre stack. Les règles par défaut sont calibrées pour le plus grand dénominateur commun. Désactivez les familles de règles qui ne s'appliquent pas à votre archi, c'est le levier numéro un contre les faux positifs.
  • Différentiel sur les PR. Sur une PR, montrez les nouveaux findings introduits par le diff, pas la dette historique. Personne ne corrige 2 000 alertes héritées pour merger un fix de typo.
  • Croiser SAST et DAST. Comme vu plus haut, la corrélation entre les deux est ce qui sépare le "peut-être exploitable" du "exploitable, prioritaire, on corrige aujourd'hui".

Quel outil, quand, et pour bloquer quoi

Le SAST et le DAST ne suffisent pas seuls : le secrets scanning et la SCA (analyse des dépendances) sont les deux compagnons indispensables, rapides et à fort rendement. Voici le tableau récapitulatif.

outils
OutilQuandVitesseBloque sur
Secrets scanCommit / PRInstantanéTout secret détecté
SCA / dépendancesPR / buildSecondesCVE high/critical exploitable
SASTPR (boîte blanche)Secondes à minutesNouveau finding high/critical
DASTStaging post-déploiementMinutes à heuresVuln runtime confirmée
Chaque outil a son moment dans le pipeline, et son propre motif de blocage.

Pour le détail des différences entre ces familles d'analyse, et ce que l'IA y change vraiment, voyez notre article pilier SAST vs DAST vs IAST : comparatif et ce que l'IA change. En pratique, ce sont surtout les grandes classes de failles du OWASP Top 10 que ce câblage attrape tôt dans le cycle.

Et concrètement, on fait comment chez own2pwn

Tout ce qui précède décrit le quoi. Le comment, c'est souvent là que ça coince : assembler, tuner et maintenir cette chaîne demande du temps que les équipes produit n'ont pas toujours. C'est exactement le problème que notre plateforme AI-Native AppSec (SecAI) cherche à résoudre : un SAST piloté par IA, la SCA filtrée par atteignabilité, l'analyse IaC et la détection de secrets en une passe, avec une GitHub Action à seuil de sévérité, un export SARIF natif pour Code Scanning, une CLI pour GitLab et Jenkins et un security gate configurable, soit une bonne partie du câblage décrit dans cet article.

Ce que SecAI couvre, et ce qu'il ne couvre pas

SecAI travaille le code et les dépendances (SAST, SCA, IaC, secrets), pas le dynamique : il n'y a pas de DAST maison. L'Action et le CLI existent et tournent, mais ne sont pas publiés sur les marketplaces publics : ils viennent avec l'abonnement, pas en un clic depuis une place de marché. La partie DAST d'un pipeline se traite avec un scanner dédié, et la profondeur avec une revue de code par un humain, ou un pentest.

Et quand vous voulez aller au-delà de l'automatisé, valider une chaîne d'exploitation complexe, challenger une logique métier, c'est là qu'intervient l'humain. Voir notre approche du pentest automatisé par IA et notre pentest web whitebox pour les audits en profondeur.

À retenir

  • SAST sur la PR (boîte blanche, rapide), DAST en staging post-déploiement (a besoin d'une appli qui tourne). Plus secrets scan + SCA au plus tôt.
  • SARIF est le format pivot : uploadé dans GitHub Code Scanning, les findings apparaissent sur la PR et dans l'onglet Security (pensez à security-events: write).
  • Le security gate ne bloque que sur high/critical (et tout secret), remonte le reste. Un gate qui crie sur tout finit désactivé.
  • Commencer petit, tuner pour sa stack, afficher le différentiel sur les PR : c'est ça, éviter l'alert fatigue.

Questions fréquentes

Où placer le SAST et le DAST dans une CI/CD ?

Le SAST se lance sur le commit ou la pull request, car il lit le code source sans rien exécuter : il bloque tôt et à moindre coût. Le DAST attaque une application déployée, on le place donc après le déploiement en staging, jamais sur chaque commit. Le secrets scanning et le SCA tournent aussi tôt, ce sont des scans rapides à fort rendement.

Qu'est-ce que le format SARIF ?

SARIF (Static Analysis Results Interchange Format) est un format JSON standardisé que la plupart des scanners savent exporter. Il évite d'accumuler un tableau de bord par outil : les findings de plusieurs analyseurs se publient au même endroit, l'onglet Security de GitHub ou les rapports de sécurité de GitLab, et s'affichent en annotations sur la pull ou la merge request.

Comment activer le SAST dans GitLab CI ?

GitLab fournit un template à inclure dans le fichier .gitlab-ci.yml, le template Jobs/SAST.gitlab-ci.yml (une variante en composant CI/CD existe aussi). Chaque analyseur produit un artefact gl-sast-report.json. Les résultats remontent dans le widget de la merge request, qui affiche les vulnérabilités nouvellement introduites ou résolues par la branche.

Le SAST de GitLab bloque-t-il la merge request ?

Pas par défaut : le job SAST réussit même s'il trouve des vulnérabilités, il se contente de les remonter. Pour empêcher la fusion, on configure une politique séparée (scan result policy ou merge request approval policy sur GitLab Ultimate), ou un job de gate maison qui échoue sur un seuil de sévérité. Le blocage est un choix explicite, pas un automatisme.

Faut-il bloquer le build sur tous les findings ?

Non, c'est le meilleur moyen de faire désactiver le gate. On ne casse le build que sur les sévérités high et critical, plus tout secret committé, et on remonte le reste dans le rapport sans bloquer. Un fichier d'exceptions versionné gère les faux positifs, et sur une pull request on n'affiche que les nouveaux findings introduits par le diff.

SAST et DAST suffisent-ils dans un pipeline ?

Ils forment le socle, mais le secrets scanning et le SCA (analyse des dépendances) sont indispensables et peu coûteux. La vraie valeur vient de la corrélation : un finding SAST confirmé exploitable par le DAST se corrige en priorité. Un pentest humain reste nécessaire pour la logique métier et les chaînes d'exploitation qu'aucun outil ne déduit.

Veille sécurité

La suite, une fois par mois

Ce qui bouge vraiment sur la surface d'attaque externe, NIS2 et la sécurité applicative, écrit par le pentester qui signe ces articles. Un envoi par mois, désinscription en un clic.

Votre adresse ne sert qu'à cet envoi. Voir la politique de confidentialité.

Articles liés