~6 minutes
Le 14 juillet 2026, pendant que la France regardait un défilé, des attaquants prenaient la main sur les pipelines de release de quatre dépôts GitHub du cœur d’AsyncAPI et publiaient cinq packages npm trojanisés sous le nom de campagne “miasma-train-p1”. Microsoft Threat Intelligence a tranché sur l’origine technique : un pull_request_target pwn request. Soit très exactement le montage que je décortiquais ici trois semaines plus tôt.
Il y a des articles dont j’aimerais autant qu’ils vieillissent mal. [Celui sur les pull_request_target ] (/2026/06/29/pwn-request-pull-request-target/) n’a pas eu cette chance. J’y écrivais que le pwn request “n’est pas une faille GitHub, c’est un motif générique qui existe partout où un trigger privilégié peut checkouter du code non vérifié”. Trois semaines après, AsyncAPI m’a fourni la démonstration, avec de vraies victimes en aval.
Note du PandaRedacteur : le sport favori du consultant sécu, c’est de dire “je vous l’avais bien dit”. Le mien, ce serait plutôt de ne jamais avoir l’occasion de le dire.
Je ne vais pas vous refaire la mécanique du pull_request_target, tout est dans l’article de juin. Ce qui m’intéresse aujourd’hui, c’est le détail de la branche de pré-production que tout le monde oublie.
Ce qui s’est passé chez AsyncAPI
Sur leurs branches principales, les mainteneurs d’AsyncAPI avaient fait le boulot. Protections strictes, revue par pairs obligatoire avant tout merge sur main => Nickel Chrome
Sauf que rien ne s’est joué sur main. Ça s’est joué sur next et schema ; deux branches de pré-production restées sans les mêmes garde-fous, probablement parce que personne ne s’est demandé si un pipeline de release pouvait s’y déclencher avec exactement les mêmes privilèges que sur la branche stable. Et bien sur la réponse => Bingo !
Note du PandaRedacteur : la branche “expérimentale”, celle qu’on garde “juste pour tester”, hérite systématiquement des permissions de prod sans hériter des contrôles de prod. On la trouve grlobalement a peut pres dans chaun des audits….
Pas de faille dans le code, pas de compte mainteneur volé : l’attaquant a joué sur un trou de process, ce qui est bien plus difficile à détecter dans un scanner. Il pousse du contenu vers ces branches non protégées, laisse le workflow pull_request_target faire le sale travail de checkout et d’exécution avec les privilèges du dépôt cible, et ressort par la voie royale du pipeline de release avec cinq packages npm trojanisés.
Vecteurs d’attaque : la fenètre, pas la porte
Ce cas ajoute une variante à l’exemple générique que j’avais construit en juin. Deux choses, en fait.
La porte blindée, la fenêtre ouverte
Verrouiller main ne vous protège de rien si next ou schema déclenchent les mêmes workflows privilégiés sans les mêmes contrôles. Et c’est précisément ce que cherche quelqu’un qui cartographie un projet open source avant de bouger : l’endroit où les protections s’arrêtent alors que les privilèges, eux, continuent tranquillement leur chemin.
Le pipeline de release, cheval de Troie
Une fois le pull_request_target exploité, plus besoin de s’attaquer à npm. L’attaquant a laissé le pipeline de release d’AsyncAPI publier pour lui. Les packages trojanisés sont donc sortis avec l’apparence de n’importe quelle version normale du projet, signés par l’infrastructure de confiance du mainteneur.
Ce que ça change dans la checklist de juin
En juin, je listais quatre réflexes : permissions par défaut en lecture seule, approbation humaine avant exécution privilégiée, runners éphémères, audit des définitions de pipeline. Je les maintiens tous les quatre. AsyncAPI m’oblige juste à écrire noir sur blanc ce que je considérais comme implicite : ces quatre réflexes s’appliquent à toute branche capable de déclencher un pipeline privilégié, pas seulement à la branche par défaut.
Note du PandaRedacteur : parfois il faut enfoncer la porte ouverte pour que les gens comprennent…
Autrement dit : tant que le pipeline de release regarde aussi next et schema, des règles limitées à main protègent le mauvais périmètre. Depuis le premier jour, et sans que personne s’en aperçoive.
Quelques références en lien
- Pwn Requests : pourquoi GitHub verrouille pull_request_target : l’article de juin, avec la mécanique générale et les mitigations par moteur CI (GitHub Actions, GitLab CI, Jenkins).
- The npm Threat Landscape: Attack Surface and Mitigations : Unit42, panorama des attaques npm 2026, AsyncAPI compris.
- Shai-Hulud, quand un ver frappe l’écosystème npm : une autre façon de compromettre un pipeline sur npm.