DevSecOps

Sécurité dans GitLab CI - Guide complet de hardening

Guide complet sécurité GitLab CI : hardening du .gitlab-ci.yml, runners, secrets, jobs isolés, SAST/DAST/SCA, supply chain, attestation SLSA.

Naim Aouaichia
17 min de lecture
  • DevSecOps
  • GitLab
  • CI/CD
  • Pipeline Security
  • Supply Chain
  • Secrets Management
  • Runner Hardening

GitLab CI est l'une des chaînes CI/CD les plus utilisées en entreprise, mais sa configuration par défaut est permissive : runners partagés, tokens larges, secrets potentiellement exposés, jobs sans isolation. Ce guide détaille les contrôles à activer côté projet, côté groupe et côté runner pour durcir une chaîne GitLab CI à un niveau de maturité sérieux, avec les commandes et extraits .gitlab-ci.yml correspondants.

1. Modèle de menace GitLab CI

Avant de durcir, il faut identifier ce qu'on protège et contre qui.

1.1 Actifs critiques

  • Code source : propriété intellectuelle, mais aussi vecteur d'introduction de portes dérobées.
  • Secrets : credentials cloud, tokens API, certificats, clés privées de signature.
  • Artefacts de build : images Docker, binaires signés, packages poussés en production.
  • Infrastructure de runners : machines qui exécutent les jobs et ont accès à tout ce que tu y routes.
  • Tokens GitLab : CI_JOB_TOKEN, Personal Access Tokens, Deploy Tokens, Group Tokens.

1.2 Attaquants probables

ProfilMotivationCapacités typiques
Contributeur externe malveillantExtraire secrets, injecter codePR sur fork, MR sur projet public
Collaborateur interne compromisEscalade, exfiltrationPush direct, modification de pipelines
Attaquant supply chainCompromission durableDépendance tierce malveillante, image de base empoisonnée
Attaquant runnerExtraction secrets, pivotRunner partagé mal isolé, registration token volé

1.3 Surfaces d'attaque spécifiques à GitLab CI

  • Pipeline injection : un attaquant modifie .gitlab-ci.yml pour exfiltrer des secrets.
  • Protected variables leak : mauvaise configuration qui expose des variables protégées sur des MR non protégées.
  • Runner pivoting : compromission d'un runner partagé qui voit passer les secrets de dizaines de projets.
  • Docker-in-Docker escape : escalade depuis un job conteneurisé vers le host.
  • MR from fork : MR ouverte depuis un fork qui exécute du code attaquant avec les droits du projet.
  • Dependency confusion : paquet privé interne imité sur un registre public.

2. Hardening du projet - réglages GitLab natifs

Avant de toucher à .gitlab-ci.yml, une série de réglages projet et groupe doivent être activés.

2.1 Branches protégées

Settings > Repository > Protected branches :

  • main, release/*, production doivent être protégées.
  • Allowed to push : No one (ou équipe restreinte seulement).
  • Allowed to merge : Maintainers minimum.
  • Require approval from code owners : activé.
  • Code owner approval : requis pour les chemins sensibles (/ci/, /terraform/, /.gitlab-ci.yml).

2.2 CODEOWNERS

Fichier à la racine du repo :

# Tout changement CI nécessite review de l'équipe plateforme
.gitlab-ci.yml         @groupe/plateforme
/ci/                   @groupe/plateforme
/terraform/            @groupe/sre
/k8s/                  @groupe/sre
 
# Dépendances = review sécurité
package.json           @groupe/appsec
package-lock.json      @groupe/appsec
go.mod                 @groupe/appsec
go.sum                 @groupe/appsec
requirements.txt       @groupe/appsec
Dockerfile             @groupe/appsec

2.3 Merge request approvals

Settings > General > Merge request approvals :

  • Prevent approval by author : activé.
  • Prevent approvals by users who add commits : activé (évite qu'un attaquant s'auto-valide).
  • Require new approvals when commits are added : activé sur main.
  • Require approval from selected users or groups : au moins 2 approbateurs sur les branches critiques.

2.4 Variables protégées et masquées

Settings > CI/CD > Variables :

  • Protected : la variable n'est exposée qu'aux jobs exécutés sur branches/tags protégées. Obligatoire pour tout credential de production.
  • Masked : la valeur est masquée dans les logs. Obligatoire pour tokens, passwords, clés.
  • Expanded : désactivé pour les variables sensibles (évite la substitution récursive).
  • File : utiliser ce type pour fichiers de configuration (kubeconfig, keystore, JSON de service account).
  • Environments scope : scope par environnement (production, staging) pour limiter l'exposition.

2.5 Désactiver l'exécution automatique depuis des forks

Settings > CI/CD > General pipelines :

  • Run pipelines for merge requests from forks : désactivé par défaut.
  • Si nécessaire pour un projet open source, activer avec limites : pas d'accès aux variables protégées (toujours le cas), pas de runner partagé sensible, review obligatoire avant chaque run.

2.6 Restrictions de push et de tag

  • Push rules (Premium/Ultimate) : bloquer les pushes qui contiennent des secrets (regex), qui créent des fichiers > 100 MB, qui ont des noms de commit non conformes, ou qui poussent sans signature GPG.
  • Signed commits obligatoires sur branches protégées : empêche un attaquant avec accès au token d'un dev de pusher sans la clé GPG associée.

3. Hardening du .gitlab-ci.yml

Le fichier pipeline est lui-même un artefact à sécuriser.

3.1 Principes directeurs

  • Principe de moindre privilège : chaque job reçoit seulement les variables et tokens dont il a besoin.
  • Pas de secrets en clair : jamais de VAR: "token_abc" dans le YAML.
  • Lisibilité maximale : YAML plat et court beat YAML ingénieux ; le YAML intelligent cache des CVEs.
  • Pinning de tout : images avec SHA256, templates inclus avec ref explicite, versions d'outils figées.

3.2 Exemple de pipeline durci

default:
  image:
    name: registry.example.com/base/alpine@sha256:abc123
    pull_policy: always
  interruptible: true
  tags:
    - private-runner
 
variables:
  GIT_DEPTH: 10
  GIT_SUBMODULE_STRATEGY: none
  SECURE_LOG_LEVEL: info
  FF_ENABLE_BASH_EXIT_CODE_CHECK: "true"
 
stages:
  - validate
  - test
  - security
  - build
  - deploy
 
include:
  - project: groupe/ci-templates
    ref: v3.2.1
    file:
      - /sast.yml
      - /container-scan.yml
 
lint:yaml:
  stage: validate
  image: cytopia/yamllint@sha256:def456
  script:
    - yamllint -s .gitlab-ci.yml
  rules:
    - if: $CI_MERGE_REQUEST_IID
 
sast:
  stage: security
  variables:
    SEMGREP_RULES: p/owasp-top-ten p/ci
  script:
    - semgrep ci --config "$SEMGREP_RULES"
  artifacts:
    reports:
      sast: gl-sast-report.json
    expire_in: 1 week
 
deploy:production:
  stage: deploy
  environment:
    name: production
    url: https://app.example.com
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: manual
  resource_group: production

3.3 Règles à retenir

  • interruptible: true : les nouveaux commits annulent les pipelines en cours, évite les deploys concurrents.
  • resource_group: production : sérialise les deploys vers un environnement critique (un seul à la fois).
  • when: manual sur production : humain dans la boucle.
  • rules: avec if: : plus lisible et plus sûr que only:/except: dépréciés.
  • tags: : force l'exécution sur un runner spécifique (pas le shared runner par défaut).

3.4 Include avec ref épinglé

Inclusions dangereuses :

include:
  - project: groupe/ci-templates
    file: /sast.yml        # PAS de ref : utilise HEAD, vulnérable à compromission

Inclusions sûres :

include:
  - project: groupe/ci-templates
    ref: v3.2.1            # Tag immuable
    file: /sast.yml
  # ou mieux :
  - project: groupe/ci-templates
    ref: 8a7b3f2e9c          # SHA précis, totalement immuable
    file: /sast.yml

3.5 Images Docker épinglées par digest

# Risqué : l'image peut changer
image: node:20
 
# Mieux : tag patch
image: node:20.11.1
 
# Idéal : digest immuable
image: node@sha256:123abc...def456

Un attaquant qui compromet un registre peut re-tag node:20 vers une image malveillante. Un digest SHA256 est cryptographiquement immuable.

4. Runner hardening

Le runner est le point sensible : il exécute le code et a accès aux secrets injectés.

4.1 Ne jamais utiliser les shared runners pour le privé sensible

Les shared runners GitLab.com sont pratiques mais :

  • Mutualisés avec tous les autres utilisateurs de la plateforme.
  • Pas de contrôle sur l'OS, les versions d'outils, les packages préinstallés.
  • Impossible d'auditer.

Pour tout projet qui manipule des secrets de production : runners dédiés.

4.2 Executor Docker - configuration durcie

config.toml du runner :

[[runners]]
  name = "prod-docker-runner"
  url = "https://gitlab.example.com"
  token = "GLRUNNER-xyz"
  executor = "docker"
 
  [runners.docker]
    image = "alpine:3.19"
    privileged = false
    disable_cache = true
    disable_entrypoint_overwrite = true
    oom_kill_disable = false
    oom_score_adjust = 100
    security_opt = ["no-new-privileges:true", "seccomp=default"]
    cap_drop = ["ALL"]
    cap_add = []
    read_only = true
    tmpfs = { "/tmp" = "rw,noexec,nosuid,size=100m" }
    shm_size = 0
    network_mode = "bridge"
    extra_hosts = []
    volumes = []
    pull_policy = "always"
 
  [runners.cache]
    Type = "s3"
    Shared = false

Points clés :

  • privileged = false : jamais true pour des runners partagés ou exposés à des MR externes.
  • cap_drop = ["ALL"] : retire toutes les capabilities Linux.
  • security_opt avec no-new-privileges et seccomp : empêche l'escalade et applique un profil seccomp.
  • read_only = true + tmpfs : système de fichiers en lecture seule avec uniquement /tmp accessible en écriture.
  • disable_cache : évite le partage de cache entre jobs potentiellement hostiles.

4.3 Executor Kubernetes - Pod Security

Pour runners Kubernetes, contraindre les pods via Pod Security Admission :

# Namespace gitlab-runner
apiVersion: v1
kind: Namespace
metadata:
  name: gitlab-runner
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

Configuration runner :

[runners.kubernetes]
  namespace = "gitlab-runner"
  cpu_limit = "2"
  memory_limit = "4Gi"
  service_cpu_limit = "1"
  service_memory_limit = "2Gi"
  [runners.kubernetes.pod_security_context]
    run_as_non_root = true
    run_as_user = 10000
    fs_group = 10000
    seccomp_profile_type = "RuntimeDefault"

4.4 Docker-in-Docker - l'exception

DinD est souvent requis pour construire des images Docker dans les jobs. Risques : nécessite privileged: true, donne accès quasi-root au host.

Alternatives plus sûres :

  • Kaniko (Google) : build d'images Docker sans daemon ni privilèges.
  • Buildah : build rootless côté Linux.
  • BuildKit rootless : mode sans privilèges.

Exemple Kaniko en GitLab CI :

build:image:
  stage: build
  image:
    name: gcr.io/kaniko-project/executor:v1.20.0-debug
    entrypoint: [""]
  script:
    - /kaniko/executor
      --context "${CI_PROJECT_DIR}"
      --dockerfile "${CI_PROJECT_DIR}/Dockerfile"
      --destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA}"
      --cache=true
      --snapshot-mode=redo

4.5 Registration tokens - rotation

Les tokens d'enregistrement de runners sont critiques. Avec GitLab 16+ :

  • Authentication tokens remplacent les registration tokens (déprécié).
  • Token scope : runner spécifique, groupe, ou instance.
  • Rotation manuelle via UI ou API (POST /runners/:id/reset_authentication_token).
  • Révoquer immédiatement toute fuite suspectée.

5. Gestion des secrets

5.1 Hiérarchie recommandée

  1. Vault ou solution équivalente : source de vérité.
  2. GitLab CI/CD Variables : pour cas simples (variable non partagée entre projets).
  3. Variables de groupe : credentials partagés à plusieurs projets d'un même groupe.
  4. Jamais dans le YAML ou dans le code.

5.2 Intégration Vault native

GitLab 13.4+ supporte l'authentification JWT OIDC vers HashiCorp Vault sans secret partagé :

variables:
  VAULT_SERVER_URL: https://vault.example.com
  VAULT_AUTH_ROLE: ci-role
 
deploy:
  id_tokens:
    VAULT_ID_TOKEN:
      aud: https://vault.example.com
  script:
    - export VAULT_TOKEN="$(vault write -field=token auth/jwt/login
        role=$VAULT_AUTH_ROLE jwt=$VAULT_ID_TOKEN)"
    - DB_PASSWORD=$(vault kv get -field=password kv/prod/db)
    - ./deploy.sh

Avantages :

  • Aucun secret Vault stocké dans GitLab.
  • Token courte durée (TTL configurable côté Vault, typiquement 5-15 min).
  • Révocable en un clic côté Vault sans toucher à GitLab.
  • Audit complet des accès côté Vault.

5.3 OIDC vers AWS/GCP/Azure

Même principe : GitLab émet un JWT signé, AWS/GCP/Azure acceptent ce JWT comme identité pour assumer un rôle, sans credential long-lived stocké dans GitLab.

deploy:aws:
  id_tokens:
    AWS_TOKEN:
      aud: https://sts.amazonaws.com
  variables:
    AWS_ROLE_ARN: arn:aws:iam::123456789012:role/gitlab-deploy
  script:
    - >
      export $(aws sts assume-role-with-web-identity
        --role-arn "$AWS_ROLE_ARN"
        --role-session-name "gitlab-ci-$CI_JOB_ID"
        --web-identity-token "$AWS_TOKEN"
        --duration-seconds 3600
        --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]'
        --output text | awk '{print "AWS_ACCESS_KEY_ID="$1"\nAWS_SECRET_ACCESS_KEY="$2"\nAWS_SESSION_TOKEN="$3}')
    - terraform apply

5.4 Secret Detection activée

GitLab propose un détecteur de secrets intégré (basé sur Gitleaks) :

include:
  - template: Security/Secret-Detection.gitlab-ci.yml
  • Scanne les commits des MR.
  • Détecte AWS keys, GitHub tokens, clés SSH, Slack webhooks, etc.
  • Résultats remontés dans l'onglet Security MR.
  • Extensible avec règles custom (.gitleaks.toml).

6. Scanners de sécurité intégrés (GitLab Ultimate)

GitLab fournit nativement plusieurs scanners activables par include template.

6.1 SAST - Static Application Security Testing

include:
  - template: Security/SAST.gitlab-ci.yml
 
variables:
  SAST_EXCLUDED_PATHS: "tests/, vendor/"
  SAST_EXCLUDED_ANALYZERS: ""

Détecte automatiquement les langages du projet et lance les analyseurs correspondants (Semgrep, Brakeman pour Ruby, gosec pour Go, etc.). Résultats exposés dans l'onglet Security des MR avec remediation advice.

6.2 Dependency Scanning

include:
  - template: Security/Dependency-Scanning.gitlab-ci.yml

Scanne les dépendances pour CVE connues. Supporte npm, pip, Maven, Gradle, Go modules, Composer, NuGet, etc.

6.3 Container Scanning

include:
  - template: Security/Container-Scanning.gitlab-ci.yml
 
variables:
  CS_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

Utilise Trivy sous le capot. Scanne les images Docker poussées au registre pour CVE dans l'OS et les libs applicatives.

6.4 DAST

include:
  - template: Security/DAST.gitlab-ci.yml
 
variables:
  DAST_WEBSITE: https://staging.example.com
  DAST_AUTH_URL: https://staging.example.com/login

Basé sur OWASP ZAP. À lancer sur un environnement de préproduction, jamais sur production directement.

6.5 License Compliance

include:
  - template: Security/License-Scanning.gitlab-ci.yml

Vérifie les licences des dépendances. Permet de bloquer l'introduction de GPL dans un projet propriétaire par exemple.

6.6 IaC Scanning

include:
  - template: Security/IaC-SAST.gitlab-ci.yml

Scanne Terraform, CloudFormation, Kubernetes manifests, Ansible avec Checkov et KICS.

7. Supply chain et attestation

7.1 Signed commits

Branches protégées avec signatures obligatoires :

  • Chaque développeur publie sa clé GPG dans son profil GitLab.
  • Configuration git locale : git config commit.gpgsign true.
  • Push rule Reject unsigned commits activée sur main.

Limite : pas de garantie sur l'auteur réel (un attaquant qui vole la clé GPG reste indiscernable), mais empêche les pushes via token volé sans clé.

7.2 Cosign et signature d'artefacts

sign:image:
  stage: deploy
  image: gcr.io/projectsigstore/cosign:v2.2.3
  id_tokens:
    SIGSTORE_ID_TOKEN:
      aud: sigstore
  script:
    - cosign sign --yes "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

Cosign en mode keyless utilise l'OIDC GitLab : la signature est attestée par Sigstore (Rekor transparency log), sans clé privée stockée nulle part.

7.3 SBOM automatique

include:
  - template: Security/Dependency-Scanning.gitlab-ci.yml
 
sbom:
  stage: build
  image: anchore/syft:v0.100.0
  script:
    - syft "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA" -o cyclonedx-json > sbom.json
  artifacts:
    paths:
      - sbom.json
    expire_in: 1 year

GitLab stocke nativement les SBOM CycloneDX depuis la version 15.7, avec matching automatique contre les CVE publiées.

7.4 Attestation SLSA

GitLab 16.0+ propose la génération automatique d'attestations SLSA Level 3 :

variables:
  RUNNER_GENERATE_ARTIFACTS_METADATA: "true"
 
build:
  stage: build
  script:
    - build-artefact.sh
  artifacts:
    paths:
      - dist/

Métadonnées générées : digest des artefacts, commit SHA, runner tag, pipeline ID, paramètres de build. Permet à un consommateur downstream de vérifier que l'artefact a bien été produit par le pipeline attendu.

8. Isolation des jobs et moindre privilège

8.1 CI_JOB_TOKEN - portée limitée

Chaque job reçoit un CI_JOB_TOKEN pour s'authentifier au registry GitLab et aux APIs internes. Depuis GitLab 15.9 :

Settings > CI/CD > Token Access :

  • Limit CI_JOB_TOKEN access : activé.
  • Allowlist des projets autorisés à utiliser le token de ce projet.

Par défaut, CI_JOB_TOKEN du projet A peut appeler l'API du projet B si le projet B est public. Avec l'allowlist, on restreint à une liste explicite.

8.2 Deploy tokens avec scope minimal

Settings > Repository > Deploy tokens :

  • Un token par usage (registry pull, package registry read, etc.).
  • Scope minimal : read_registry seul si le job n'a qu'à tirer une image.
  • Expiration définie (90 jours max).
  • Nom explicite pour traçabilité.

8.3 Environments protégés

Settings > CI/CD > Protected environments :

  • L'environnement production ne peut être déployé que par des groupes autorisés.
  • Required approvals : humain obligatoire avant chaque deploy vers production.
  • Toute variable scoped production n'est exposée qu'aux jobs autorisés sur cet environnement.

8.4 Éviter before_script global bavard

Un before_script: global qui s'exécute avant tous les jobs dilue la surface d'attaque. Chaque job hérite des variables, des clones, des configurations. Préférer des before_script locaux, minimum nécessaire.

9. Audit et observabilité

9.1 Audit events

Admin > Monitoring > Audit events (self-managed Ultimate) :

  • Toute action sensible loguée : changement de permission, création de token, modification de variable CI/CD, push vers branche protégée.
  • Export vers SIEM via Elasticsearch ou webhook.

9.2 Logs de jobs

  • Activation de la rétention longue sur branches protégées.
  • Export vers stockage externe (S3, GCS) si obligations réglementaires.
  • Masquage des secrets vérifié par échantillonnage.

9.3 Monitoring runners

  • Métriques Prometheus exposées par le runner (listen_address dans config.toml).
  • Alertes sur : taux d'échec anormal, jobs qui dépassent la durée moyenne, consommation CPU/RAM atypique (signal d'exfiltration).
  • Vérification périodique des tags runners (un runner non tagué prend tous les jobs qui ne précisent pas de tag).

9.4 Compliance framework

GitLab Ultimate permet de définir des compliance frameworks au niveau groupe : pipelines forcés d'inclure certains templates, check automatique que ces pipelines ont bien tourné avant merge.

Exemple : tout projet taggé framework: pci-dss doit inclure obligatoirement /compliance/sast.yml, /compliance/container-scan.yml, /compliance/sbom.yml.

10. Patterns dangereux à éviter

Anti-patternPourquoi c'est dangereuxRemplacer par
image: docker:latestTag mouvant, pas de pinningDigest SHA256 ou tag patch figé
tags absent sur jobs sensiblesExécution sur shared runner GitLab.comTag explicite vers runner dédié
Secret en clair dans YAMLExposé à tout reviewer et dans l'historique GitVariable protégée ou Vault
privileged: true sur runner DockerEscape container trivialKaniko, BuildKit rootless
CI_JOB_TOKEN utilisé partoutPortée trop large, pivot facileAllowlist + Deploy token scoped
include sans refVulnérable à compromission du templateref: v1.2.3 ou SHA précis
Script qui curl | bashSupply chain risk, pas d'intégritéPinning version + checksum
Job sans rules: strictesExécution sur branches non vouluesrules: - if: $CI_COMMIT_BRANCH == "main"
Cache partagé entre projetsFuite d'artefacts entre projetsCache scoped projet + S3 chiffré
Logs verbeux sur credentialsExfiltration via logsMasking + audit post-mortem des logs

11. Plan de hardening en 5 étapes

Pour une équipe qui part d'une configuration GitLab CI par défaut :

Étape 1 (semaine 1) - hygiène de base

  • Audit des variables CI/CD : identifier les secrets non masked, non protected, ou orphelins.
  • Protéger main, interdire push direct.
  • Activer Secret Detection template.
  • Rotation de tous les tokens historiques.

Étape 2 (semaines 2-3) - runners dédiés

  • Déployer runners Docker ou Kubernetes dédiés pour les projets sensibles.
  • Configurer config.toml durci (privileged off, cap_drop, seccomp).
  • Migrer les projets sensibles des shared runners vers les dédiés.

Étape 3 (mois 2) - scanners activés

  • SAST, Dependency Scanning, Container Scanning inclus dans tous les projets.
  • Compliance framework si GitLab Ultimate.
  • Seuils d'alerte configurés sans bloquer les merges (phase observation).

Étape 4 (mois 3) - secrets modernes

  • Intégration Vault ou OIDC cloud provider pour les projets production.
  • Suppression progressive des credentials long-lived des variables CI/CD.
  • Policy de rotation automatique pour ce qui reste.

Étape 5 (mois 4-6) - supply chain

  • Signed commits sur branches protégées.
  • Cosign pour signer les images avant push registry.
  • SBOM automatique et matching CVE.
  • Attestation SLSA Level 3.

12. Checklist de revue pipeline

Avant tout merge sur main qui touche .gitlab-ci.yml, vérifier :

  • Images épinglées par digest ou tag patch figé
  • include: avec ref immuable uniquement
  • Aucun secret en clair dans le YAML
  • tags: explicite pour runners dédiés sur jobs sensibles
  • rules: qui excluent les MR de forks sur jobs sensibles
  • interruptible: true sur jobs non critiques
  • resource_group sur jobs production
  • Jobs production avec when: manual ou approvals
  • Artefacts avec expire_in: défini
  • Scanners security activés et à jour
  • Pas de privileged: true hors Kaniko/BuildKit justifié
  • Audit trail : qui a modifié quoi, quand, pourquoi (commit message)

13. Verdict et posture Zeroday

GitLab CI fournit un socle très complet, mais par défaut il vise la facilité d'usage plus que la sécurité. Un projet production sérieux doit investir une à trois semaines pour passer d'un pipeline démo à un pipeline durci.

Les deux chantiers qui rapportent le plus vite : runners dédiés (élimine 80 % du risque d'exfiltration croisée) et scanners activés en observation (révèle la dette sécurité cachée). Le reste (supply chain, SLSA, OIDC) est une maturation progressive sur 6 à 12 mois, justifiée par le niveau d'exposition réel du produit.

Pour approfondir côté rôle : voir les ressources métier DevSecOps et roadmap DevSecOps. Côté technique pur, SAST vs DAST complète les scanners décrits ci-dessus.

Écrit par

Naim Aouaichia

Expert cybersécurité et fondateur de Zeroday Cyber Academy

Expert cybersécurité avec un master spécialisé et un parcours hybride : développement, DevOps, DevSecOps, SOC, GRC. Fondateur de Hash24Security et Zeroday Cyber Academy. Formateur et créateur de contenu technique sur la cybersécurité appliquée, la sécurité des LLM et le DevSecOps.