Une faille XSS dans les logs de build de SourceHut permettait de pirater des comptes
Un log de build piégé pouvait exécuter un script dans le navigateur d'un utilisateur de SourceHut. ansi2html 1.9.4 corrige la faille CVE-2026-92973, qui touchait les versions 1.7.0 à 1.9.3.
3 min de lecture

Un chercheur en sécurité a révélé une faille qui permettait à un log de build piégé de prendre le contrôle de comptes SourceHut. Le bug se trouvait dans ansi2html, une bibliothèque Python qui transforme la sortie colorée d'un terminal en HTML, et il est suivi sous la référence CVE-2026-92973. Tout projet qui affiche des logs non fiables avec ansi2html dans les versions 1.7.0 à 1.9.3 est exposé de la même façon.
SourceHut est une forge logicielle hébergée, un service pour les dépôts Git, les listes de diffusion et l'intégration continue. Son service de CI, builds.sr.ht, exécute des jobs et affiche leurs logs dans le navigateur. Le chercheur, qui publie sous le nom d'Arusekk, a décrit l'attaque le 23 septembre 2026.
Comment un log de build est devenu une attaque
L'attaque reposait sur le cross-site scripting, ou XSS. Il s'agit d'amener un site web à exécuter le JavaScript d'un attaquant dans le navigateur d'un visiteur, avec la session connectée de ce visiteur.
Les terminaux comprennent les séquences d'échappement, des codes cachés mêlés à la sortie texte. La plupart définissent des couleurs. L'une d'elles, OSC 8, transforme un morceau de texte en lien hypertexte cliquable. ansi2html traduit ces codes en HTML pour qu'un log ait le même aspect sur une page web.
D'après l'article, ansi2html n'échappait pas correctement la cible du lien dans les séquences OSC 8. Un job pouvait afficher une séquence dont le "lien" sortait de l'attribut HTML et en ajoutait de nouveaux, dont un gestionnaire d'événement qui exécute du code. Quiconque ouvrait la page de log de ce job l'exécutait.
Ce qu'un attaquant pouvait faire
Le script injecté pouvait lire le jeton CSRF de la page, écrit le chercheur. Un jeton CSRF est le secret qu'un site utilise pour confirmer qu'une requête provient vraiment de la session de l'utilisateur. Avec lui, le script pouvait soumettre des jobs de build au nom de la victime et atteindre ses clés de déploiement, les identifiants que les jobs utilisent pour pousser du code ou publier des versions.
| Logiciel concerné | Versions vulnérables |
|---|---|
| ansi2html | De 1.7.0 jusqu'à 1.9.4, non incluse |
| builds.sr.ht | De 0.40.0 jusqu'à 0.105.1, non incluse |
L'article ne signale aucune exploitation documentée dans la nature.
La chronologie de la divulgation
SourceHut a réagi vite. Le correctif de la bibliothèque en amont a pris un mois de plus, et la divulgation publique a attendu que les deux soient disponibles.
| Date (2026) | Événement |
|---|---|
| 1er août | Bug signalé |
| 4 août | Mesure d'atténuation déployée sur builds.sr.ht |
| 2 septembre | Sortie d'ansi2html 1.9.4 avec le correctif |
| 17 septembre | Attribution de CVE-2026-92973 |
| 23 septembre | Publication de l'article public |
Les notes de version d'ansi2html 1.9.4 sur GitHub présentent le correctif sous le titre "osc8: ensure proper escaping", pull request 263. Arusekk a écrit le correctif et le mainteneur hartwork l'a approuvé.
Pourquoi auditer la dépendance ne suffisait pas
Le chercheur soulève un point qui dépasse ce bug. La faille se trouve dans du code qui change d'une version à l'autre, si bien qu'une revue ponctuelle ne peut pas la détecter. "Note how even carefully auditing ansi2html would not save SourceHut, unless redone on every bump", indique l'article.
Une dépendance sûre au moment de votre revue peut acquérir plus tard une nouvelle fonctionnalité. Une simple montée de version apporte alors cette fonctionnalité, et tout bug qu'elle contient, directement dans votre produit.
SourceHut a fait parler de lui cette année pour ses règles de contribution, notamment son interdiction du code et des tickets assistés par LLM. Cette divulgation rappelle que le propre code du service a une chaîne d'approvisionnement, comme celui de tout le monde.
Ce que cela signifie pour les développeurs
Mettez ansi2html à jour vers la version 1.9.4 ou ultérieure partout où vous l'utilisez. Fouillez vos lockfiles et vos images de conteneur, pas seulement vos dépendances directes, car la bibliothèque arrive souvent comme dépendance d'un outil de test ou de CI. Lancer pip show ansi2html dans chaque environnement vous indique la version que vous livrez réellement.
Traitez la sortie de build comme une entrée hostile. Un log de CI contient tout ce que le code d'une pull request a choisi d'afficher. Si votre propre tableau de bord affiche les logs en HTML, vérifiez que chaque valeur d'attribut est échappée. Ajoutez une Content Security Policy qui bloque les gestionnaires d'événements en ligne, afin qu'un échappement oublié ne devienne pas une exécution de code.
Examinez ce qu'une session volée pourrait atteindre. Ici, une seule consultation de page donnait le pouvoir de lancer des jobs et de lire des clés de déploiement. Limitez les clés de déploiement à un seul dépôt et renouvelez celles dont vous ne pouvez pas justifier l'usage.
Enfin, relisez les changelogs quand une bibliothèque de rendu ou d'analyse ajoute une fonctionnalité. La prise en charge de nouvelles séquences d'échappement, un nouveau balisage ou une nouvelle gestion des liens sont exactement les changements qui méritent un second regard.
Sources
- SourceHut account takeover via build logs - arusekk.pl
- ansi2html v1.9.4 - GitHub
Articles liés

Node.js 22.23.3 LTS corrige un bug use-after-free dans HTTP/2
Node.js 22.23.3 LTS, publié le 23 septembre, corrige un bug use-after-free dans HTTP/2, ajoute la prise en charge de SharedArrayBuffer à Node-API et passe à OpenSSL 3.5.8.

Radicle jusqu'à 1.10.3 envoie les dépôts privés en clair
Toutes les versions de Radicle jusqu'à 1.10.3 envoient les données des dépôts sans chiffrement et laissent un attaquant imiter un pair de confiance. Aucun correctif pour l'instant.

Gzip 1.15 corrige une course qui supprimait le mauvais fichier
Gzip 1.15 apporte 119 commits issus de 75 semaines de travail. Il corrige une course pouvant supprimer le mauvais fichier et un dépassement de tampon en .lzh.