Mika Ayenson, PhD

Abus du pipeline CI/CD : le problème que personne ne surveille

Comment nous avons construit un modèle de CI open-source qui utilise l'extraction de signaux et le raisonnement LLM pour détecter les abus de CI/CD dans les actions GitHub, le CI GitLab et les pipelines Azure DevOps.

9 minutes de lectureDetection Engineering, Enablement, Tools

Préambule

Sur les sites 2025 et 2026, nous avons observé un schéma qui s'applique à l'ensemble du secteur. Les attaquants ont cessé de s'attaquer directement aux serveurs de production et ont commencé à cibler l'automatisation qui s'y déploie. Des identifiants de développeur compromis, un fichier de flux de travail modifié, et soudain chaque secret d'un environnement CI/CD est transmis à un point de terminaison contrôlé par un attaquant. Nous avons vu ce phénomène se produire lors d'incidents impliquant de grands projets de logiciels libres, des entreprises figurant sur la liste Fortune 500 et des outils d'infrastructures critiques.

La chaîne d'attaque est d'une simplicité trompeuse :

Identifiants de développeur volés → Fichier de flux de travail modifié → Secrets de CI récoltés → Déplacement latéral vers le nuage et la production

Aujourd'hui, nous mettons en open-sourcing cicd-abuse-detector, un modèle de CI qui utilise l'extraction de signaux basée sur les regex et l'analyse LLM pour détecter les changements suspects dans les pipelines CI/CD. Il fonctionne sur GitHub Actions, GitLab CI et Azure DevOps, et est conçu autour des techniques d'attaque du monde réel documentées dans la recherche publique sur la sécurité.

Principaux points abordés dans cet article

  • Les environnements CI/CD sont des cibles de grande valeur car un seul flux de travail compromis peut exfiltrer simultanément des informations d'identification dans le nuage, des jetons de registre de paquets, des clés de signature de code, des clés de déploiement et des jetons OIDC.
  • L'outil extrait plus de 50 signaux de regex et de métadonnées des diffs, puis les transmet avec le diff complet à Claude pour une analyse structurée des menaces. Pas de Python, pas de dépendances au-delà de bash et de l'interface de programmation de Claude Code.
  • Les modèles de détection ont été testés par rapport à des boîtes à outils offensives telles que Nord Stream et Gato-X, et par rapport à des incidents réels tels que ArtiPACKED et HackerBot-Claw.
  • Le projet est livré avec 19 exemples de diffs malveillants et quatre exemples de diffs bénins modélisés d'après des incidents spécifiques, ainsi qu'une suite de tests automatisés qui valide chaque signal.

Pourquoi les pipelines CI/CD sont-ils une cible privilégiée ?

Si vous passez du temps à examiner les actions GitHub ou les configurations CI GitLab, vous remarquerez peut-être à quel point la confiance est concentrée dans ces fichiers. Un flux de travail de déploiement typique a accès aux informations d'identification AWS, aux jetons de publication npm, aux mots de passe Docker Hub et à un jeton GitHub avec des autorisations d'écriture, le tout en même temps. La surface d'attaque n'est pas un serveur avec un CVE, c'est un fichier YAML.

Collecte de données d'identification à grande échelle

Un attaquant ayant volé les informations d'identification d'un développeur modifie un flux de travail pour exfiltrer les secrets disponibles dans l'environnement CI. La campagne GhostAction de septembre 2025 en a fait la démonstration à grande échelle, en compromettant 327 les utilisateurs de GitHub dans 817 dépôts. 3 325 secrets ont été volés par le biais de fichiers de flux de travail injectés qui transmettaient des informations d'identification aux points de terminaison des attaquants.

Le ver npm de Shai-Hulud est allé plus loin. Cette attaque qui se propage d'elle-même a récolté des jetons d'accès personnels GitHub via le jeton d'authentification gh, a exécuté TruffleHog pour la reconnaissance secrète, et a utilisé les jetons compromis pour injecter silencieusement du code malveillant dans d'autres paquets appartenant au même développeur. Plus de 46 000 paquets malveillants ont été publiés au cours de la seule première vague.

Exploitation de déclencheurs privilégiés

Le déclencheur pull_request_target est l'une des fonctionnalités les plus dangereuses des actions GitHub. Contrairement à un déclencheur pull_request classique, il exécute les flux de travail dans le contexte du référentiel de base avec accès aux secrets, mais il peut exécuter du code à partir d'un fork non fiable. La recherche Orca "Pull Request Nightmare" l'a démontré pour les dépôts de Google, Microsoft et NVIDIA.

En février 2026, une campagne automatisée appelée HackerBot-Claw a systématiquement analysé les dépôts publics à la recherche de cette configuration erronée. Il a utilisé cinq techniques d'exploitation différentes, notamment des fonctions Go init() empoisonnées, l'injection de commandes par nom de branche, l'injection par nom de fichier, l'injection directe de scripts et l'injection d'invites AI contre des réviseurs de code basés à Claude. Dans le cas le plus grave, le référentiel Trivy d'Aqua Security a été entièrement compromis, ce qui a conduit à une attaque de la chaîne d'approvisionnement en aval qui a exposé 33 000 secrets sur près de 7 000 machines. Comme cela a été démontré, cette attaque de la chaîne d'approvisionnement a été rendue possible grâce à des jetons compromis qui étaient encore valables plusieurs semaines après avoir été initialement volés.

Le reste de la taxonomie

Au-delà de la collecte de données d'identification et de l'exploitation des déclencheurs, le modèle de menace couvre quatre catégories supplémentaires qui apparaissent régulièrement dans la recherche publique :

  • L'escalade des permissions, où l'ajout de permissions : write-all ou id-token : write élargit le rayon d'action de toute compromission.
  • Ciblage des exécutants, redirection des tâches vers des exécutants auto-hébergés qui ont souvent un accès réseau à l'infrastructure interne, ou spécification d'images de conteneurs contrôlées par les attaquants.
  • Manipulation de la chaîne d'approvisionnement par le biais de références d'actions mutables (utilisation de @main au lieu de versions SHA-pinées), exécution de scripts à distance (curl | bash), échanges de registres de fichiers de verrouillage et empoisonnement de dépendances.
  • Évasion de la défense par la manipulation de l'horodatage des livraisons, ce qui fait apparaître les fichiers malveillants comme anciens et fiables. KL4R10N a documenté cette technique dans des campagnes liées à la RPDC, où des commandes rétroactives font référence à des infrastructures qui n'existaient pas à la date déclarée.

Chacune d'entre elles correspond à des techniques spécifiques de MITRE ATT& CK : T1552 (informations d'identification non sécurisées), T1195 (compromission de la chaîne d'approvisionnement), T1070.006 (complication temporelle) et T1059 (interprète de commandes et de scripts).

Fonctionnement du détecteur

Nous voulions que les modèles fonctionnent sans avoir recours à Python, à des moteurs d'exécution personnalisés ou à des dépendances complexes. Tout fonctionne avec des utilitaires shell standards sur un runner ubuntu-latest par défaut, et le seul outil installé est le Claude Code CLI via npm, qui gère l'authentification, les tentatives, et le routage des modèles.

Étape 1 : Filtre et diff

Lorsqu'une demande d'extraction est ouverte (ou qu'une poussée arrive sur une branche protégée), le flux de travail identifie les fichiers modifiés à travers trois niveaux de chemins pertinents pour CI/CD. Le premier niveau couvre les fichiers CI de base tels que les définitions de flux de travail, les configurations de pipeline et les Makefiles. Le second couvre les artefacts de construction et de publication tels que les Dockerfiles, les manifestes de paquets, les lockfiles et les scripts de signature ou de déploiement. Le troisième niveau récupère les configurations de l'environnement de développement comme .vscode/tasks.json et .devcontainer des dossiers.

Chaque fichier est différencié individuellement et limité à 10 000 caractères. Nous procédons par fichier plutôt que globalement, car un seul cap sur le diff combiné est un vecteur de contournement. Un attaquant peut compléter une modification malveillante du flux de travail par une importante modification bénigne d'un fichier Docker afin de dépasser la limite de caractères de l'exploit.

Étape 2 : Extraction du signal

Avant que le LLM ne voie quoi que ce soit, plus de 50 modèles de regex analysent chaque diff à la recherche de modèles dangereux connus. Ces signaux sont consultatifs. Ils ne transmettent jamais l'analyse, mais ils fournissent au LLM un résumé des menaces présélectionnées. Quelques exemples :

SignalModèleCe qu'il attrape
secrets_context${{.*secrets.Interpolation secrète directe dans les flux de travail
pull_request_targetpull_request_targetLe dangereux déclencheur qui donne des secrets au code RP
checkout_refref:.*github.event.pull_request.head.(sha|ref)Code PR non fiable vérifié dans un contexte privilégié
double_base64base64.*|.*base64Double codage pour éviter le masquage des journaux (technique Nord Stream)
ld_preloadLD_PRELOADExécution de code arbitraire via l'injection de variables d'environnement
vscode_auto_taskrunOn.*folderOpenVS Code task that executes on folder open (Contagious Interview)

La liste des signaux est basée sur des outils adverses réels, notamment Nord Stream et Gato-X, et testée contre 19 exemples de diffs malveillants modélisés d'après des incidents spécifiques.

Le détecteur fonctionne de manière identique sur GitHub Actions, GitLab CI et Azure DevOps. Voici les détections tirées sur chaque plateforme :

Étape 3 : Analyse du programme d'éducation et de formation tout au long de la vie

Le résumé du signal, le diff complet, le profil de l'auteur et les métadonnées du commit sont regroupés et envoyés à Claude via le CLI de Claude Code. L'invite d'analyse fait passer le modèle par plusieurs domaines :

  1. Compréhension des différences et évaluation des risques par fichier
  2. Interprétation des signaux en fonction du contexte (un signal seul n'est pas un verdict)
  3. Analyse temporelle des modifications rétroactives
  4. Évaluation de la confiance des auteurs à l'aide de l'âge du compte, de l'historique des contributions et de l'appartenance à une organisation
  5. Étalonnage de la gravité par rapport à une table de combinaison de signaux comportant plus de 60 entrées
  6. Reconnaissance des faux positifs (par exemple, cURL pour le téléchargement d'outils connus n'est pas une exfiltration)
  7. Recommandations concrètes et réalisables ("Pin actions/setup-node@main to a specific SHA" instead of "review carefully")

Le résultat est un verdict JSON structuré contenant la gravité, la confiance, le raisonnement, les preuves et les recommandations, tous validés par rapport à un schéma JSON.

Étape 4 : Alerte et portail

En fonction de la gravité du verdict, le flux de travail publie un résumé d'étape, crée un problème, envoie une notification Slack et, éventuellement, échoue à la vérification des RP si la gravité atteint un seuil configuré.

Les alertes dans Slack et GitHub Issues résolvent le problème de la notification immédiate, mais elles ne vous donnent pas un historique consultable. Chaque verdict produit par le détecteur (par ex. bénigne, suspecte ou malveillante), peut éventuellement être envoyée à Elasticsearch sous forme de document structuré dans le fichier logs-cicd.abuse-default flux de données. Le flux de travail envoie le verdict avec les métadonnées CI/CD (plateforme, référentiel, acteur, type d'événement, URL d'exécution) dans un index unique qui couvre les trois plateformes prises en charge.

C'est là que la corrélation entre les plates-formes devient pratique. Une alerte GitHub Actions et une alerte GitLab CI provenant du même acteur atterrissent dans le même flux de données, interrogeable dans une seule instruction ES|QL :

FROM logs-cicd.abuse-* 
WHERE verdict.verdict IN ("malicious", "suspicious") AND @timestamp > NOW() - 7 days 
EVAL platform = cicd.platform, repo = cicd.repository, actor = cicd.actor, severity = verdict.severity
KEEP @timestamp, platform, repo, actor, severity
SORT @timestamp DESC

Le schéma comprend cicd.platform, cicd.repository, cicd.actor, et l'objet verdict complet (verdict, sévérité, confiance, résumé, raisons, preuves), ce qui facilite l'élaboration de règles de détection. Une campagne coordonnée qui touche plusieurs dépôts en l'espace d'une heure, un récidiviste signalé sur plusieurs plates-formes ou un pic de résultats critiques justifiant une page de réponse à l'incident peuvent être mis en corrélation.

Validation par rapport à des attaques réelles

Pour valider la couverture, nous avons comparé nos modèles de détection au code source réel des outils offensifs, aux recherches publiées et aux analyses post-mortem publiques.

Nord Stream : correspondance verbatim de la charge utile

Nord Stream est l'outil open-source d'extraction de secrets CI/CD de Synacktiv qui prend en charge GitHub, GitLab et Azure DevOps. Nous avons extrait les sources du générateur YAML (nordstream/yaml/github.py) et comparé ses modèles de sortie avec nos exemples de différences.

  • Le modèle de charge utile de GitHub utilise env -0 | awk -v RS='0' '/^secret_/ {print $0}' | base64 -w0 | base64 -w0. Notre site nord-stream-pipeline-exfil.diff contient cette ligne mot pour mot, et nos signaux double_base64, env_null_dump et env_secret_grep sont tous activés.
  • Le modèle OIDC Azure utilise azure/login@v1 avec les autorisations id-token: write suivies du compte az get-access-token | base64 -w0 | base64 -w0. Notre diff capture ce flux exact et déclenche cloud_auth_action et id_token_write.
  • Les techniques du pipeline Azure DevOps (addSpnToEnvironment pour l'exposition des identifiants SPN, DownloadSecureFile pour le vol de fichiers sécurisés, le patching de la source des tâches SSH via la modification de ssh.js ) sont toutes présentes dans nord-stream-azure-devops.diff et détectées par des signaux spécifiques à la plateforme.

ArtiPACKED : la condition de course à l'artefact

La recherche ArtiPACKED de l'unité Palo Alto 42 a montré que le téléchargement de l'intégralité du répertoire d'extraction en tant qu'artefact entraîne la fuite du fichier .git/config contenant le fichier GITHUB_TOKEN. L'API d'artefact v4 autorisant les téléchargements en cours d'exécution, un pirate peut extraire et utiliser le jeton avant que le travail ne soit terminé.

Notre site artifact-token-leak.diff reproduit exactement ce modèle, en utilisant upload-artifact avec path: . (tout l'espace de travail). Le signal upload_artifact l'attrape et le LLM évalue si l'étendue du téléchargement inclut le répertoire .git.

Injection de GITHUB_ENV : LD_PRELOAD à RCE

Les recherches de Legit Security sur Google Firebase et Apache ont montré que l'écriture d'une entrée non fiable dans $GITHUB_ENV permet à un attaquant de définir des variables d'environnement arbitraires telles que LD_PRELOAD et NODE_OPTIONS, ce qui permet d'exécuter du code dans des flux de travail privilégiés.

Notre site github-env-injection.diff reproduit cette technique avec trois charges utiles distinctes : LD_PRELOAD pointant vers un objet partagé malveillant, NODE_OPTIONS avec une injection requise et $GITHUB_PATH manipulation. Les signaux github_env_write, ld_preload et github_path_write se déclenchent tous comme prévu.

Interview contagieuse : La configuration de l'IDE comme accès initial

La campagne Contagious Interview, attribuée à la RPDC, cible les développeurs par le biais de faux entretiens d'embauche, en distribuant des dépôts contenant des fichiers .vscode/tasks.json qui s'exécutent automatiquement à l'ouverture d'un dossier. La présentation est cachée (reveal: never, echo: false), et la charge utile utilise curl | node pour une exécution silencieuse.

Notre site ide-config-poisoning.diff capture la chaîne d'attaque complète, y compris le déclencheur d'exécution automatique (runOn: folderOpen), la présentation cachée, la charge utile curl | node, l'entrée files.exclude qui cache le répertoire .vscode, et un crochet de post-installation trojanisé avec des URL codées en base64 et eval() pour l'exécution de code. Six signaux le captent en même temps.

Défenses recommandées

Outre le déploiement du détecteur, voici quelques mesures de renforcement qui découlent directement des schémas d'attaque que nous avons étudiés :

  • Épinglez toutes les actions au CSA, pas les étiquettes, pas les branches. Les références épinglées par SHA empêchent les attaques de modification rétroactive des balises telles que tj-actions (CVE-2025-30066).
  • Étendez les secrets à des étapes individuelles plutôt que d'utiliser des variables d'environnement au niveau du travail. Chaque étape ne doit avoir accès qu'aux secrets dont elle a réellement besoin.
  • Utilisez des jetons éphémères de courte durée lorsque cela est possible afin de réduire la surface d'attaque.
  • Évitez de consulter le site pull_request_target, sauf en cas de nécessité absolue. Si vous devez l'utiliser, ne vérifiez jamais le code de l'en-tête du PR dans le même flux de travail. Utilisez un site workflow_run-triggered workflow distinct pour les opérations qui nécessitent à la fois des secrets et un contexte de relations publiques.
  • Définissez des autorisations explicites pour chaque flux de travail, car les autorisations par défaut sont beaucoup trop larges. Définissez permissions: {} au niveau du flux de travail et ajoutez des autorisations spécifiques pour chaque travail.
  • Activez persist-credentials: false lors du checkout car le comportement par défaut d'actions/checkout persiste le GITHUB_TOKEN dans le répertoire .git. Si vous téléchargez des artefacts, ce jeton les accompagne.

Résumé

Les pipelines CI/CD sont devenus une surface d'attaque majeure pour la compromission de la chaîne d'approvisionnement. L'automatisation qui rend possible la livraison de logiciels modernes est ce que les attaquants exploitent pour recueillir des informations d'identification, empoisonner des paquets et pivoter vers l'infrastructure en nuage. L'examen traditionnel du code ne permet pas de détecter ces modèles car ils sont subtils, spécifiques à une plateforme et conçus pour ressembler à des changements DevOps légitimes.

La combinaison de l'extraction de signaux basée sur des expressions rationnelles avec le raisonnement LLM nous permet de mettre en évidence ces modèles au stade de la demande d'extraction, avant qu'ils n'atteignent la production. Le dépôt comprend le modèle de menace complet, la suite de tests et des exemples de différences si vous souhaitez creuser les détails ou l'adapter à votre propre environnement.

Pour commencer, consultez le repo cicd-abuse-detector pour les instructions d'installation, le modèle de menace complet et les exemples de différences. Nous sommes toujours intéressés par les nouveaux schémas d'attaque et les nouvelles idées de détection. Discutez avec nous sur notre communauté Slack et posez vos questions sur nos forums de discussion.

Abus de CI/CD par MITRE ATT&CK

Nous utilisons le cadre MITRE ATT& CK pour cartographier les tactiques, les techniques et les procédures que les adversaires utilisent contre les pipelines CI/CD.

Tactiques

TactiquePertinence de la CI/CD
Accès aux justificatifs (TA0006)Récolter les secrets des environnements de CI
Exécution (TA0002)Exécution de commandes dans les gestionnaires de pipeline
Persistance (TA0003)Déclencheurs programmés, flux de travail basés sur des crons
Défense Evasion (TA0005)Manipulation de l'horodatage des engagements, contournement du masquage des journaux
Accès initial (TA0001)Compromission des informations d'identification des développeurs, hameçonnage pour les PAT
Mouvement latéral (TA0008)Utiliser les informations d'identification récoltées dans le nuage pour pivoter

Techniques

TechniqueApplication CI/CD
T1552 : Références non sécuriséesSecrets exposés dans les variables d'environnement de l'IC, les artefacts et la mémoire du programme d'exécution
T1195.002 : Compromettre la chaîne d'approvisionnement des logicielsActions, dépendances et fichiers de verrouillage empoisonnés
T1059 : Interprète de commandes et de scriptscurl
T1070.006 : TimestompDes dates de livraison antidatées pour éviter les révisions
T1098 : Manipulation de compteEscalade de permissions via write-all, id-token : write
T1078 : Comptes validesLes PAT de développeur volés sont utilisés pour modifier les flux de travail

Références

Les éléments suivants ont été référencés tout au long de la recherche ci-dessus :

À propos d'Elastic Security Labs

Elastic Security Labs est la branche d'Elastic Security spécialisée dans le renseignement sur les menaces et dont l'objectif est d'apporter des changements positifs dans le paysage des menaces. Elastic Security Labs fournit des recherches accessibles au public sur les menaces émergentes avec une analyse des objectifs stratégiques, opérationnels et tactiques des adversaires, puis intègre ces recherches aux capacités intégrées de détection et de réponse d'Elastic Security.

Suivez Elastic Security Labs sur Twitter @elasticseclabs et consultez nos recherches sur www.elastic.co/security-labs/.

Partager cet article