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 :
| Signal | Modèle | Ce qu'il attrape |
|---|---|---|
secrets_context | ${{.*secrets. | Interpolation secrète directe dans les flux de travail |
pull_request_target | pull_request_target | Le dangereux déclencheur qui donne des secrets au code RP |
checkout_ref | ref:.*github.event.pull_request.head.(sha|ref) | Code PR non fiable vérifié dans un contexte privilégié |
double_base64 | base64.*|.*base64 | Double codage pour éviter le masquage des journaux (technique Nord Stream) |
ld_preload | LD_PRELOAD | Exécution de code arbitraire via l'injection de variables d'environnement |
vscode_auto_task | runOn.*folderOpen | VS 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 :
- Compréhension des différences et évaluation des risques par fichier
- Interprétation des signaux en fonction du contexte (un signal seul n'est pas un verdict)
- Analyse temporelle des modifications rétroactives
- Évaluation de la confiance des auteurs à l'aide de l'âge du compte, de l'historique des contributions et de l'appartenance à une organisation
- Étalonnage de la gravité par rapport à une table de combinaison de signaux comportant plus de 60 entrées
- Reconnaissance des faux positifs (par exemple, cURL pour le téléchargement d'outils connus n'est pas une exfiltration)
- 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 sitenord-stream-pipeline-exfil.diffcontient cette ligne mot pour mot, et nos signauxdouble_base64,env_null_dumpetenv_secret_grepsont tous activés. - Le modèle OIDC Azure utilise
azure/login@v1avec les autorisationsid-token: writesuivies du compte azget-access-token | base64 -w0 | base64 -w0. Notre diff capture ce flux exact et déclenchecloud_auth_actionetid_token_write. - Les techniques du pipeline Azure DevOps (
addSpnToEnvironmentpour l'exposition des identifiants SPN,DownloadSecureFilepour le vol de fichiers sécurisés, le patching de la source des tâches SSH via la modification dessh.js) sont toutes présentes dansnord-stream-azure-devops.diffet 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 siteworkflow_run-triggered workflowdistinct 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: falselors du checkout car le comportement par défaut d'actions/checkout persiste leGITHUB_TOKENdans 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
| Tactique | Pertinence 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
| Technique | Application CI/CD |
|---|---|
| T1552 : Références non sécurisées | Secrets 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 logiciels | Actions, dépendances et fichiers de verrouillage empoisonnés |
| T1059 : Interprète de commandes et de scripts | curl |
| T1070.006 : Timestomp | Des dates de livraison antidatées pour éviter les révisions |
| T1098 : Manipulation de compte | Escalade de permissions via write-all, id-token : write |
| T1078 : Comptes valides | Les 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 :
- https://github.com/elastic/cicd-abuse-detector
- https://github.com/synacktiv/nord-stream
- https://github.com/AdnaneKhan/Gato-X
- https://unit42.paloaltonetworks.com/github-repo-artifacts-leak-tokens/
- https://blog.gitguardian.com/ghostaction-campaign-3-325-secrets-stolen
- https://www.reversinglabs.com/blog/shai-hulud-worm-npm
- https://orca.security/resources/blog/pull-request-nightmare-github-actions-rce/
- https://orca.security/resources/blog/hackerbot-claw-github-actions-attack/
- https://www.stepsecurity.io/blog/hackerbot-claw-github-actions-exploitation
- https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability-0
- https://www.abstract.security/blog/contagious-interview-tracking-the-vs-code-tasks-infection-vector
- https://about.codecov.io/apr-2021-post-mortem/
- https://kl4r10n.tech/blog/when-git-history-lies
- https://www.synacktiv.com/en/publications/github-actions-exploitation-dependabot
- https://docs.anthropic.com/en/docs/claude-code
À 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/.