- Un chercheur partage comment il a découvert une vulnérabilité dans Nixpkgs qui aurait permis d’injecter du code malveillant dans l’ensemble de l’écosystème Nix
- Il explique le risque structurel de GitHub Actions avec le déclencheur
pull_request_target, qui peut exposer des privilèges sensibles et des secrets même dans les PR de contributeurs externes
- Il démontre qu’il était réellement possible d’élever ses privilèges dans les tâches editorconfig-checker et de validation des code owners via l’injection de commandes et l’usage de liens symboliques
- Dès la découverte, l’équipe de maintenance de Nixpkgs a rapidement corrigé la vulnérabilité, désactivé les workflows vulnérables et réévalué la gestion des permissions
- Il souligne l’importance de séparer les données non fiables des opérations sensibles dans l’infrastructure CI/CD, d’appliquer le principe du moindre privilège et de renforcer les politiques de sécurité
Pirater tout l’écosystème Nix
Introduction et contexte
- Lors de la NixCon de l’an dernier, le chercheur et sa collègue Lexi ont présenté une vulnérabilité dans Nixpkgs
- Cette faille ouvrait la voie à une attaque de la chaîne d’approvisionnement, avec la possibilité d’injecter du code malveillant dans tout l’écosystème Nix
- De la détection à la divulgation puis à la remédiation, la réponse a été menée en une seule journée
- Le chercheur ne pouvant pas assister à la NixCon cette année, il détaille ici l’ensemble du processus
GitHub Actions : une cible vulnérable
- GitHub Actions est un système qui prend en charge diverses tâches d’automatisation (CI/CD) dans les dépôts de code
- Dès lors qu’un accès aux fichiers de workflow est possible, l’injection de code devient facile, ce qui en fait une cible majeure pour les attaques de la chaîne d’approvisionnement
- Les fichiers de workflow sont écrits en YAML et ne sont pas conçus comme un format d’exécution, ce qui peut entraîner des vulnérabilités de sécurité inattendues
- Un exemple simple consiste en un workflow qui exécute des commandes lorsqu’un code est poussé
Le déclencheur dangereux pull_request_target
- GitHub Actions propose plusieurs déclencheurs, et pull_request_target diffère fortement du
pull_request classique
pull_request_target dispose par défaut de droits read/write et d’un accès aux secrets, y compris pour les forks (PR)
- En cas de mauvaise utilisation de ce déclencheur, des données externes non fiables se retrouvent combinées à des privilèges sensibles
- La documentation officielle de GitHub met elle aussi clairement en garde contre ce risque
- Le chercheur a examiné 14 workflows utilisant
pull_request_target dans le dépôt Nixpkgs
Vulnérabilité dans editorconfig-checker
- Le premier workflow vulnérable découvert servait à vérifier les règles editorconfig
- Après avoir calculé la liste des fichiers modifiés, celle-ci était transmise à editorconfig-checker via
xargs
- En ignorant les avertissements de sécurité liés à la commande
xargs, on ouvrait une faille permettant d’injecter des noms de fichiers conçus de manière malveillante (par exemple --help)
- Cela rendait possible la manipulation arbitraire d’editorconfig-checker, voire l’exécution de commandes supplémentaires (une analyse plus poussée serait nécessaire sur ce point)
Vulnérabilité dans codeowners-validator : inclusion de fichiers locaux
- Une seconde vulnérabilité, plus grave, a été découverte dans le workflow de validation du fichier CODEOWNERS
- Ce processus faisait un checkout du code de la PR, puis vérifiait le fichier avec codeowners-validator
- L’auteur de la PR pouvait remplacer un fichier OWNERS par un lien symbolique, afin de référencer un fichier arbitraire sur le runner (par exemple des identifiants d’action)
- Lors de la validation, le contenu de ce fichier était alors affiché dans les logs, ce qui entraînait la divulgation d’un token GitHub disposant de droits read/write
- Une fois ce token obtenu, il devenait possible de pousser directement dans le dépôt Nixpkgs
Mesures prises et enseignements
- Après le signalement de la faille, le mainteneur de Nixpkgs infinisil a réagi immédiatement
- Désactivation temporaire des workflows vulnérables
- Correction et séparation des points de contact entre données non fiables et privilèges
- Après les correctifs de sécurité, renommage des workflows pour atténuer les problèmes de ciblage de branche
- Principaux enseignements
- Ne jamais combiner, ou alors avec une extrême prudence, des données non fiables avec des secrets ou des opérations sensibles
- Respecter le principe du moindre privilège
- Il est indispensable de bien connaître les guides officiels de GitHub sur les permissions dans Actions
- En cas de vulnérabilité similaire, les administrateurs peuvent désactiver GitHub Actions à l’échelle de l’organisation via les politiques prévues à cet effet (des instructions de configuration sont disponibles)
Conclusion
- En une seule journée, le chercheur a découvert, signalé et aidé à corriger une vulnérabilité capable de mettre en danger tout l’écosystème Nix
- Cela montre à quel point il faut faire preuve d’une grande prudence avec GitHub Actions, en particulier lors de l’usage de
pull_request_target
- Il remercie Intrigus de KITCTF pour son aide dans la recherche, ainsi qu’infinisil pour sa réponse rapide
- Les lecteurs intéressés sont encouragés à consulter la vidéo de la présentation et les ressources complémentaires
- Plus globalement, le texte met en avant l’importance de la sécurité de GitHub Actions et les leçons concrètes à en tirer
1 commentaires
Avis Hacker News
Je pense que
pull_request_targetest fondamentalement vulnérable du point de vue de la sécurité, et que GitHub devrait tout simplement supprimer cette fonctionnalité. En général, on dit qu’on peut utiliserpull_request_targeten toute sécurité tant qu’on n’exécute pas pendant le job du code contrôlé depuis la branche, mais en pratique la surface de vulnérabilité est bien plus large à cause d’attaques comme l’injection d’arguments ou l’inclusion de fichiers locaux. Aujourd’hui, les seuls cas d’usage légitimes sont surtout l’ajout automatique de labels ou de commentaires sur des PR tierces. Je ne vois pas pourquoi il faudrait, pour ce type de tâches, accorder par défaut des droits d’écriture sur le dépôt. GitHub devrait pouvoir émettre un jeton limité strictement à cette opération. C’est pour ça que dans zizmor, je signale systématiquement l’usage de déclencheurs dangereux commepull_request_target; voir zizmor dangerous triggerspull_requestne se déclenche pas. Là,pull_request_targetest en pratique la seule option. Ce serait mieux que GitHub propose plutôt un réglage permettant d’exécuter des workflows sur des PR à merge non propre, désactivé par défaut et réservé à des usages comme les linters. En attendant, c’est vraiment regrettable qu’à cause de cette limite on soit forcé de n’utiliser quepull_request_target. À noter que si on utilise ce genre d’outils externes, faire un merge manuel dans GitHub casse tout le flux ; il ne faut jamais faire de merge manuelpull_request_targetpour deux raisons. D’abord, le workflow s’exécute toujours par rapport à main, ce qui permet de bloquer du code de test non vérifié. Ensuite, dans la sous-revendication du JWT du workflow,job_workflow_refest fourni de manière déterminante, ce qui permet un contrôle d’accès fin dans des systèmes basés sur OIDCpull_request_targets’exécute dans le contexte de base de la PR, ce qui est censé empêcher du code malveillant de voler le dépôt ou les secrets. Mais en réalité, quand on voit à quel point l’exfiltration de secrets est facile, la situation en devient presque ridiculeSi l’équipe Nix avait adopté, comme je l’avais proposé dans la RFC, des builds reproductibles signés indépendamment des commits/reviews signés, ce type d’attaque supply chain de dernière étape aurait été impossible. Au fond, NixPkgs veut que n’importe qui puisse éditer facilement, et a peur que toute tentative sérieuse autour de la sécurité fasse fuir les bénévoles ; l’objectif est de se concentrer sur une distribution de loisir. C’est acceptable, mais si l’on veut être clair avec les gens sur cette réalité et protéger ce qui a de la valeur, il faut arrêter d’utiliser ou de recommander Nix dans des environnements critiques du point de vue de la sécurité. Un OS censé protéger quelque chose devrait exiger une signature matérielle rigoureuse à deux parties pour chaque changement, et ne jamais faire reposer la confiance sur une seule machine ou une seule personne. C’est pour cela que j’ai créé Stagex lien Stagex lien Codeberg
J’ai conçu des systèmes informatiques de manière traditionnelle pendant longtemps, et je trouve toujours très déroutant que les workflows modernes continuent d’émettre des bearer tokens, même de courte durée, à des programmes auxquels on fait confiance. Si le framework GitHub Actions ne fournissait qu’un accès à un socket Unix privilégié ou à
ssh-agent, ce genre de vulnérabilité serait bien plus difficile à exploiterLes actions CI/CD sur les pull/merge requests sont un véritable cauchemar. Quand un développeur écrit des tests ou des étapes de validation, il pense généralement dans le cadre « mon code s’exécute dans le contexte de mon compte GitHub/GitLab ». Cela vaut pour ses propres commits ou ceux de son équipe, mais sur une PR, le pipeline CI/CD exécute du code non fiable. Il est difficile de garder cette distinction constamment à l’esprit de manière exacte, et tant qu’on se limite à des tests simples ou à des linters, ça passe, mais dès qu’il faut intégrer de l’infrastructure et obtenir plus de privilèges, cela devient vite dangereux
pull_requestetpull_request_target). L’un (par exemplepull_request) est quasiment sûr sauf en cas de très mauvaise utilisation, tandis que l’autre (par exemplepull_request_target) ne peut pratiquement pas être utilisé en toute sécurité. Plus grave encore, GitHub a fait en sorte que des tâches ordinaires comme poser un label sur une PR ou laisser un commentaire automatique ne soient possibles qu’avec le déclencheur dangereux (pull_request_target), ce qui pousse tout le monde vers un choix instable. Les fonctions fournies par GitHub Actions ont une structure qui favorise les erreursAvec le temps, je m’inquiète de plus en plus des attaques supply chain. Ce n’est pas seulement la peur de « perdre mon travail à cause de ça » ou de voir apparaître de nouveaux vecteurs d’attaque dans NixOS, CI/CD, Node, etc., c’est une inquiétude plus philosophique. Plus on dépend de ces choses, plus les problèmes à gérer s’accumulent inévitablement. Même ce qu’on voudrait utiliser sereinement est déjà devenu trop embrouillé — VSCode, Emacs, Nix, Vim, Firefox, JS, Node, et tous les plugins et paquets de dépendances qui s’entremêlent. Du coup, et c’est presque honteux à dire, je me rapproche de plus en plus de l’idée étrange qu’il faudrait revenir au papier et à une technologie minimale, vraiment simple, juste pour retrouver un semblant de contrôle ou de sécurité. Je sais que ce n’est pas rationnel, mais cette complexité me fatigue de plus en plus. J’ai même l’impression d’atteindre ma propre limite de complexité
La page de manuel de xargs contient un avertissement disant qu’« il n’est pas possible d’utiliser xargs en toute sécurité ». Mais ce problème de sécurité est différent du cas appliqué ici. Dans la situation présente, il suffit d’ajouter
--à la fin pour l’éviterLa phrase « il n’est pas possible d’utiliser xargs en toute sécurité » est souvent mal comprise. Par exemple, si on exécute
cat "$HOME/changed_files" | xargs -r editorconfig-checker --, on peut éviter le problème précis dont il est question ici<div>{escapeHtml(value)}</div>pour chaque valeur HTML afin d’éviter les XSS. Si on doit appliquer manuellement les règles d’usage sûr partout, c’est que l’approche de départ est déjà mauvaise--, et la plupart des usages de xargs sont vulnérables à l’injection d’arguments. En ce sens, c’est comparable au fait que toute exécution de commande est intrinsèquement dangereuse. Ce n’est pas vraiment la faute de xargs lui-même ; le vrai problème est la réalité d’outils réutilisés à répétition dans des contextes de privilèges variésCet article contient une faille critique d’une portée bien plus large : dans le code de la PR, on peut remplacer le fichier OWNERS par un lien symbolique pour exposer des fichiers arbitraires comme le fichier de credentials de github actions. Comme git permet de valider des liens symboliques, ce risque existe dans presque n’importe quel workflow
pull_request_target, les credentials sont ceux du dépôt cible, c’est-à-dire le dépôt dans lequel on va merger. Avecpull_request, ce sont les credentials du dépôt source contrôlé par l’attaquantLa seule « bonne » nouvelle, c’est qu’OpenBSD et NetBSD utilisent encore CVS pour la gestion des paquets, donc ils ne sont pas affectés par cette vulnérabilité. Je ne sais pas pour FreeBSD. D’une certaine manière, la sécurité vient ici d’un effet d’obscurité. Cela dit, ces projets semblent eux aussi envisager une migration vers git, et OpenBSD pourrait passer à got(1)