2 points par GN⁺ 2026-04-29 | 1 commentaires | Partager sur WhatsApp
  • Un défaut du protocole interne sur le chemin git push suffisait à permettre une exécution de code à distance sur le backend ; GitHub.com a déjà été atténué, mais GHES doit recevoir le correctif
  • Une push option, entrée contrôlée par l’utilisateur, était recopiée telle quelle dans l’en-tête X-Stat, ce qui permettait d’injecter un nouveau champ avec un simple point-virgule ; le comportement last-write-wins, où la dernière valeur d’une même clé écrase la précédente, a été exploité
  • En combinant parmi les champs injectables rails_env, custom_hooks_dir et repo_pre_receive_hooks, il était possible de contourner le sandbox et d’exécuter des hooks depuis un chemin choisi par l’attaquant avec les privilèges de l’utilisateur git
  • Le même mécanisme permettait aussi d’injecter le flag enterprise mode de GitHub.com, confirmant une exécution de code sur un shared storage node, puis un état permettant de lire les dépôts d’autres utilisateurs et organisations présents sur ce nœud
  • Cela montre que, dans une architecture multiservice où différents services se fient à un format partagé, l’absence de nettoyage des entrées, un chemin d’exécution non productif et l’absence de validation des chemins peuvent se combiner pour produire une vulnérabilité majeure

Réponse immédiate et périmètre d’impact

  • Sur GitHub.com, le problème a déjà été atténué et aucune action supplémentaire n’est nécessaire
  • GitHub Enterprise Server nécessite une intervention immédiate ; il faut mettre à niveau vers GHES 3.19.3 ou supérieur, qui inclut le correctif de CVE-2026-3854
  • La plage de versions vulnérables est GHES 3.19.1 et antérieures ; les versions corrigées indiquées sont 3.14.24, 3.15.19, 3.16.15, 3.17.12, 3.18.6, 3.19.3
  • Au moment de la rédaction, 88 % des instances GHES étaient encore vulnérables
  • Les informations techniques complémentaires et les procédures de remédiation de GitHub sont disponibles sur le blog sécurité de GitHub
  • Les clients Wiz peuvent identifier les instances GHES vulnérables avec les requêtes préconstruites du Wiz Threat Center

Contexte de l’enquête et approche

  • L’infrastructure git interne de GitHub traite tout le flux git push, au travers de plusieurs services internes écrits dans différents langages de programmation
  • Dans ce type de structure multiservice, les différences de façon dont chaque composant analyse et approuve les données partagées peuvent devenir des vulnérabilités
  • Jusqu’ici, extraire et auditer la grande quantité de binaires compilés en boîte noire constituant ce pipeline demandait un temps considérable et beaucoup de travail manuel
  • Des outils augmentés par l’IA et une rétro-ingénierie automatisée basée sur IDA MCP ont permis d’analyser rapidement les binaires compilés et de reconstituer le protocole interne
  • Au cours du processus, les points où une entrée utilisateur influence le comportement du serveur tout au long du pipeline ont été suivis de manière systématique, ce qui a permis d’identifier un défaut fondamental dans l’ensemble du flux d’entrée

Architecture interne et frontières de confiance

  • Lorsqu’un git push arrive via SSH, la requête suit le flux babeld, gitauth, gitrpcd, puis le pre-receive hook
  • babeld est le point d’entrée de toutes les opérations git ; il reçoit la connexion SSH, puis transmet l’authentification à gitauth
  • gitauth vérifie les identifiants de l’utilisateur et ses droits de push sur le dépôt, puis renvoie des politiques de sécurité comme les limites de taille de fichier ou les règles de nommage de branche
  • Sur cette base, babeld construit l’en-tête interne X-Stat contenant des métadonnées de sécurité
  • gitrpcd reçoit l’en-tête X-Stat pour configurer l’environnement des processus suivants et fait totalement confiance à babeld sans authentification propre
  • Le pre-receive hook vérifie, avant l’acceptation du push, les limites de taille de fichier, les règles de nommage de branche, l’intégrité LFS et les hooks personnalisés définis par les administrateurs
  • Le lien central était l’en-tête X-Stat, qui contient des paires key=value séparées par ;
  • Les services internes découpent X-Stat sur ; puis remplissent une map ; lorsqu’une même clé apparaît deux fois, la valeur la plus récente écrase la précédente selon la règle last-write-wins
  • babeld ajoute aussi à X-Stat les push options transmises via git push -o, sous des champs comme push_option_0, push_option_1 et push_option_count

Cause de la vulnérabilité : injection de champs X-Stat

  • babeld copiait dans l’en-tête X-Stat la valeur de push option, contrôlée par l’utilisateur, sans nettoyer les points-virgules
  • Comme ; est le séparateur de champs de X-Stat, un seul point-virgule dans une push option permettait de sortir du champ d’origine et de créer un nouveau champ contrôlé par l’attaquant
  • Par exemple, en injectant large_blob_rejection_enabled=bool:false dans push_option_0, la valeur bool:true définie plus tôt se retrouvait écrasée par la valeur plus tardive
  • Ce comportement a été confirmé à la fois par l’analyse des binaires et par des captures réseau sur une instance GHES réelle
  • La combinaison de rétro-ingénierie et d’analyse au niveau du trafic a permis de cartographier les champs X-Stat injectables
  • Les champs particulièrement sensibles côté sécurité identifiés étaient rails_env, custom_hooks_dir, repo_pre_receive_hooks, large_blob_rejection_enabled, reject_sha_like_refs, user_operator_mode
  • Parmi eux, les trois champs rails_env, custom_hooks_dir et repo_pre_receive_hooks étaient au cœur de la chaîne menant à l’exécution de code à distance

La chaîne menant au RCE sur GHES

  • GHES prend en charge les custom pre-receive hooks, exécutés avant l’acceptation d’un push
  • Le binaire pre-receive comportait deux chemins d’exécution qui ne différaient que par la valeur rails_env issue de X-Stat
  • Si la valeur était production, le hook s’exécutait dans un sandbox ; pour toute autre valeur, il s’exécutait directement avec les privilèges de l’utilisateur de service git, sans sandbox ni isolation
  • Injecter une valeur non productive dans rails_env permettait donc de contourner le sandbox
  • Ensuite, l’injection de custom_hooks_dir donnait à l’attaquant le contrôle du répertoire de base dans lequel le script de hook était recherché
  • Enfin, en injectant dans repo_pre_receive_hooks une définition de hook contenant une traversée de chemin, la résolution de chemin du binaire combinait le répertoire contrôlé par l’attaquant et la charge de traversée pour pointer vers un chemin arbitraire du système de fichiers
  • Le chemin d’exécution non productif lançait alors directement ce chemin résolu, sans argument, sans sandbox et sous l’utilisateur de service git
  • Lors de la validation réelle, une seule commande git push a renvoyé la sortie uid=500(git), confirmant un RCE avec les privilèges de l’utilisateur git
  • Avec ces privilèges, il était possible d’obtenir un contrôle total sur l’instance GHES, y compris la lecture et l’écriture sur le système de fichiers ainsi que la visibilité sur la configuration des services internes

Extension à GitHub.com et exposition inter-locataires

  • Lorsque la même chaîne d’exploitation a été appliquée à un dépôt GitHub.com, le push réussissait d’abord, mais les custom hooks ne s’exécutaient pas
  • En injectant user_operator_mode=bool:true et en comparant les sorties de débogage des deux plateformes, il est apparu que GitHub.com n’atteignait pas le chemin de code des custom hooks
  • Une rétro-ingénierie complémentaire a montré qu’un booléen contrôlant le comportement enterprise mode du serveur existait dans l’en-tête X-Stat
  • Sur GHES, ce flag vaut true par défaut, ce qui active toujours le chemin des custom hooks ; sur GitHub.com, la valeur par défaut est false, ce qui empêche normalement d’atteindre ce chemin
  • Comme ce flag pouvait lui aussi être injecté via le même mécanisme, l’ajout d’un champ supplémentaire rendait la chaîne d’exploitation complète fonctionnelle sur GitHub.com également
  • Ensuite, le résultat de l’exécution de hostname a été renvoyé depuis l’infrastructure GitHub.com, confirmant un RCE sur GitHub.com
  • GitHub.com est une plateforme multitenant, où les dépôts de multiples utilisateurs et organisations sont stockés sur une infrastructure backend partagée
  • L’exécution de code a eu lieu sur un shared storage node ; à cet endroit, l’utilisateur git dispose de larges permissions sur le système de fichiers afin de traiter toutes les opérations sur les dépôts présents sur le nœud
  • Si cet utilisateur est compromis, les dépôts d’autres organisations et utilisateurs présents sur le nœud peuvent eux aussi être lus, indépendamment de leur propriétaire
  • L’énumération des entrées d’index des dépôts accessibles sur les deux nœuds compromis a montré des millions d’entrées par nœud, incluant des dépôts d’autres utilisateurs et organisations
  • Le contenu réel des dépôts d’autres locataires n’a pas été consulté ; seuls des comptes de test internes ont été utilisés pour vérifier que les permissions système de l’utilisateur git autorisaient la lecture de tous les dépôts du nœud

Enseignements clés et calendrier de divulgation

  • Un simple git push suffisait à exploiter un défaut du protocole interne pour obtenir une exécution de code à distance sur l’infrastructure backend
  • Quand plusieurs services écrits dans différents langages s’échangent des données via un protocole interne partagé, les hypothèses de confiance de chaque service deviennent elles-mêmes une surface d’attaque
  • Dans cette chaîne, un service insérait tel quel la valeur d’une push option, un autre faisait confiance à tous les champs de X-Stat, et le pre-receive hook supposait qu’en production rails_env serait production
  • Les chemins de code non productifs au sein des binaires de production, l’absence de validation contre la traversée de chemin dans les scripts de hook et l’absence de nettoyage des entrées dans un protocole fondé sur des délimiteurs sont des schémas qui peuvent exister dans d’autres bases de code
  • Les équipes qui exploitent des architectures multiservices doivent particulièrement vérifier comment des entrées contrôlées par l’utilisateur circulent dans les protocoles internes, surtout lorsque des paramètres sensibles pour la sécurité dérivent de formats de données partagés
  • Dans cette recherche, des outils de rétro-ingénierie augmentée par l’IA, dont IDA MCP, ont permis d’accélérer fortement l’analyse de binaires compilés et la reconstitution de protocoles internes
  • À mesure que ces outils gagnent en maturité, ils devraient jouer un rôle croissant dans l’identification de classes de vulnérabilités nécessitant une analyse inter-composants approfondie
  • D’après le calendrier de divulgation, la vulnérabilité d’injection de push option dans X-Stat a été découverte le 2026-03-04 ; le même jour, le RCE a été confirmé sur GHES 3.19.1, signalé à GitHub, et le correctif GitHub.com a été déployé
  • Le 2026-03-10, CVE-2026-3854 et un CVSS 8.7 ont été attribués, puis le correctif GHES a été publié
  • Le 2026-04-28, la vulnérabilité a été rendue publique

1 commentaires

 
GN⁺ 2026-04-29
Réactions sur Hacker News
  • Cela revient à faire en sorte que l’en-tête de sécurité critique défini par un service d’authentification interne inclue aussi une chaîne arbitraire fournie par l’utilisateur final via git push -o
    c’est facile à dire après coup, mais là, c’est quand même complètement aberrant

  • L’approche de reverse engineering assisté par l’IA montre bien les points forts actuels des agents LLM
    comme ce sont des modèles énormément entraînés sur du code, ils peuvent fortement accélérer la compréhension des entrailles de systèmes complexes
    la recherche en sécurité consiste souvent à la fois à 1) comprendre des mécanismes internes compliqués et 2) y trouver une vulnérabilité,
    et il arrive souvent qu’une fois le vrai mécanisme interne révélé, la vulnérabilité elle-même devienne étonnamment facile à voir
    CVE-2026-3854 n’était pas un cas immédiatement obvious même en connaissant l’interne,
    mais si cette injection de commande avait été exposée sur une surface d’attaque plus traditionnelle ou plus accessible, elle aurait probablement été découverte très vite

    • À l’origine, il y avait déjà des signes que l’IA était particulièrement forte pour le reverse engineering C++ ou pour porter en masse du C++ en C simple
      mais ces derniers temps, on a l’impression que cet élan s’est un peu brouillé, ou qu’il est volontairement freiné par ceux qui veulent préserver le lock-in dev/vendor créé par la complexité syntaxique du C++
  • On dirait presque qu’il y a quelqu’un de Wiz ici, tellement le résultat semble solide
    le produit tient encore plutôt bien malgré une croissance extrême et une inflation de fonctionnalités,
    et l’équipe sécurité trouve régulièrement des choses vraiment intéressantes

    • Beaucoup viennent de l’unité 8200
    • Il y a trop de bruit, donc nous on n’utilise qu’un pipeline maison avec osv-scanner et trivy pour ne regarder que le critique
    • Je n’y travaille pas, mais quand on l’essaie dans notre boîte, ça déclenche sans arrêt des alertes pour des actions totalement inoffensives
      alors qu’en revanche, pour des opérations un peu suspectes comme interroger un DC en CLI et réinitialiser des identifiants, silence radio, ce qui est assez frustrant
  • Quand babeld relaie une requête push, il place les push options dans l’en-tête X-Stat de la requête interne,
    et cette valeur est une chaîne arbitraire fournie par l’utilisateur via git push -o
    sauf qu’ils ont copié la valeur telle quelle sans assainir les points-virgules,
    or ; sert de séparateur de champs dans X-Stat, ce qui permet de sortir du champ d’origine et de créer de nouveaux champs contrôlés par l’attaquant
    c’est vraiment le niveau de l’erreur la plus basique possible, au point que le fruit semblait si bas qu’il était enterré sous terre

    • Ah, la mère de Bobby Tables était vraiment maligne
  • Même si la vulnérabilité a été détectée avant toute exploitation connue,
    je me demande s’il était nécessaire d’alimenter la panique avec des formulations comme BREAKING, unauthorized access ou millions of repositories
    https://x.com/wiz_io/status/2049153209982140718

    • Cela dit, ces formulations ne sont pas inexactes non plus
      GitHub a simplement eu de la chance que ce soit le fuzzing de Wiz qui tombe dessus, et non un acteur étatique
  • Le fait que 88 % des instances GHES n’aient toujours pas appliqué un correctif de sécurité critique publié il y a 7 semaines paraît assez grave
    https://docs.github.com/en/enterprise-server@3.19/admin/release-notes#3.19.3

    • GHES est en pratique dans un état quasi abandonné depuis des années
      appliquer ne serait-ce qu’une release de patch nécessite plusieurs heures d’indisponibilité,
      et il n’existe même pas de méthode de mise à niveau HA officiellement supportée, ce qui empêche même les clients consciencieux de suivre rapidement les dernières versions
      quand on se plaint, on nous dit de migrer vers GitHub Enterprise Cloud,
      mais on peut se demander combien de gens accepteraient cela aussi facilement dans le contexte actuel
      cela dit, GHES a au moins un avantage : il ne tombe pas pendant les pannes quotidiennes de github.com
    • Une grande partie des clients on-prem place GHES derrière un VPN,
      et semble vouloir programmer la mise à niveau à une date avec peu d’impact opérationnel
      en revanche, si l’instance est publique, il faut la mettre à jour immédiatement
      avec les informations de l’article et le code source public de GitHub Enterprise, il ne semble pas difficile de reconstituer une méthode de reproduction
    • En entreprise, on peut très bien lancer une mise à jour hors calendrier, tout casser et devoir en répondre,
      ou suivre le planning prévu en espérant qu’il n’arrive rien ; en général, c’est la seconde option qui l’emporte
    • Dans les environnements où l’on ne peut pas utiliser github.com parce qu’on prend la sécurité très au sérieux,
      voir un produit on-prem n’être mis à jour qu’une fois par an n’a rien d’étonnant
    • Dans les grosses installations, le point clé est la fragilité du processus de mise à niveau
      sur les logiciels d’entreprise avec beaucoup de données, il suffisait souvent d’un détail mineur pour casser l’installation et forcer l’équipe ops à revenir en arrière
      les anciennes mises à niveau de SharePoint donnaient presque l’impression de lancer les dés
  • C’est encore un gros succès pour Wiz,
    et on a l’impression d’un moment charnière qui montre à quel point les outils IA poussent le RE et la découverte de chemins de compromission

    • Cela fragilise aussi l’argument selon lequel ne pas publier le code source empêcherait davantage les attaques par l’IA
      c’est un point de donnée supplémentaire montrant qu’en sécurité, on ne doit pas s’appuyer sur la security through obscurity
  • Tout le monde parle de remplacer GitHub, mais il reste la question de savoir par quoi
    si même un acteur comme GitHub finit par sortir une RCE, il est difficile d’affirmer sereinement qu’une autre alternative fera mieux

    • On peut toujours plaisanter en disant que Thomas Dohmke va tout régler avec un nouveau projet
      https://news.ycombinator.com/item?id=46961345
      https://news.ycombinator.com/item?id=47712656
    • La réponse la plus réaliste semble être de garder Forgejo auto-hébergé comme forge d’origine,
      et d’utiliser GitHub uniquement comme miroir tant qu’on profite du CI gratuit
      les secrets peuvent être confiés à un fournisseur d’hébergement de secrets séparé
    • Nous avons migré de GitHub vers Forgejo auto-hébergé il y a 6 mois et ça fonctionne très bien
      j’ai encore du mal à croire que Forgejo soit devenu aussi réactif et GitHub aussi lent
    • Nous séparons désormais clairement les projets internes et les projets publics
      les projets internes sont hébergés sur une instance Forgejo privée, et les projets publics sont publiés sur GitHub tout en étant répliqués vers Forgejo
      j’ai été surpris de voir à quel point Forgejo est essentiellement un binaire unique facile à configurer,
      et comme tous nos services internes pointent vers Forgejo, quitter GitHub un jour causerait peu de friction
    • Un GitLab auto-hébergé derrière un VPN peut aussi très bien faire l’affaire
      une image Docker tout-en-un et quelques GitLab runners suffisent largement pour des équipes petites à moyennes,
      et il n’y a aucune raison de se compliquer la vie avec la version Kubernetes à moins d’en avoir réellement besoin
  • C’était déjà impressionnant de voir une IA trouver des vulnérabilités dans du code source,
    mais le faire jusque dans des exécutables binaires est vraiment stupéfiant
    le potentiel est énorme, pour le meilleur comme pour le pire
    et, encore une fois, cela rappelle qu’il ne faut pas traiter des données comme des commandes
    toutes les entrées utilisateur doivent être assainies

    • Le Transformer a été conçu à l’origine pour la traduction
      donc le fait qu’il soit bon en source-to-source ou text-to-source n’avait rien de surprenant,
      et il n’est peut-être pas si étonnant non plus qu’il s’adapte bien à la compréhension d’une version asm
      cela reste malgré tout impressionnant
  • Je me demande s’il sera possible de déterminer si cela a réellement été exploité

    • À mon avis, cette vulnérabilité semble exploitable même par un utilisateur anonyme
      les logs HTTP/git permettront peut-être de vérifier dans une certaine mesure s’il y a eu exploitation,
      mais il est possible qu’ils ne permettent pas de savoir exactement à quoi l’attaquant a accédé ni qui l’a fait
      si l’exploit pouvait s’exécuter de manière autonome sur le serveur git, alors par définition il pouvait échapper à la journalisation