Un workflow peut passer actionlint, zizmor, poutine et un gate de posture à zéro finding, et rester dangereux. Les scanners détectent des motifs connus ; ils ignorent ce que vos secrets ouvrent, où vos runners sont branchés, et qui consomme vos artefacts. Cette page donne une méthode en sept questions pour établir ce qu'un workflow expose réellement, et décider quoi corriger en premier.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Situer ce qu'un scanner voit et ce qu'il ne peut pas voir
- Dérouler les sept questions sur un workflow quelconque
- Repérer la frontière de confiance, l'endroit où une donnée non fiable entre
- Évaluer le rayon d'explosion plutôt que la seule probabilité
- Choisir quels workflows modéliser en premier, et quand refaire l'exercice
Ce qu'un scanner ne peut pas savoir
Section intitulée « Ce qu'un scanner ne peut pas savoir »Les scanners raisonnent sur le fichier. Ils lisent un permissions:, une
référence d'action, une interpolation dangereuse. C'est précieux, et c'est
borné : trois catégories d'information leur échappent par construction.
| Ce que le scanner voit | Ce qu'il ignore |
|---|---|
secrets.DEPLOY_TOKEN est passé par env: | Que ce jeton ouvre la production de toute l'entreprise |
runs-on: [self-hosted, prod] | Que cette machine est sur le réseau d'administration |
| Une image est poussée sur un registre | Que quarante dépôts la consomment en base |
permissions: contents: write | Que ce dépôt est la source d'une action utilisée ailleurs |
Aucune de ces colonnes de droite n'est inscrite dans le YAML. Elles dépendent de votre contexte, et c'est exactement ce qu'une modélisation de menace formalise. Le scanner répond « ce workflow contient-il un motif dangereux connu ». La modélisation répond « que se passe-t-il si celui-ci est compromis ».
Les sept questions
Section intitulée « Les sept questions »L'enchaînement suit le trajet réel d'une attaque : entrer, exécuter, obtenir, sortir, propager. Chaque question se répond en une ligne, et c'est le passage d'une question à la suivante qui révèle les enchaînements dangereux.
1. Qui peut déclencher ce workflow ? | v2. Quel code s'exécute, et d'où vient-il ? | v3. Sur quelle machine, dans quel segment réseau ? | v4. Avec quel jeton, et quelles permissions ? | v5. Quels secrets sont présents dans l'environnement ? | v6. Vers où la machine peut-elle émettre du trafic ? | v7. Quel artefact est produit, et qui le consomme ensuite ?1. Qui peut déclencher ?
Section intitulée « 1. Qui peut déclencher ? »C'est la question qui détermine toutes les autres, parce qu'elle fixe la population d'attaquants possibles. Un workflow que seuls trois mainteneurs déclenchent et un workflow que n'importe quel inconnu déclenche par une pull request n'appellent pas le même niveau d'exigence.
| Déclencheur | Qui peut l'actionner |
|---|---|
push sur une branche protégée | Les personnes ayant le droit d'écriture, après revue |
pull_request | N'importe qui, sur un dépôt public |
pull_request_target | N'importe qui, avec les secrets du dépôt cible |
issue_comment, issues | N'importe qui |
workflow_dispatch | Les personnes ayant accès au dépôt |
schedule | Personne, mais s'exécute sans surveillance |
Les deux lignes du milieu concentrent l'essentiel des incidents publics. La
ligne schedule mérite une mention particulière : un workflow planifié tourne
sans témoin, souvent la nuit, ce qui allonge le délai de détection.
2. Quel code s'exécute ?
Section intitulée « 2. Quel code s'exécute ? »Il ne suffit pas que le déclencheur soit sûr : encore faut-il savoir quel code tourne. Quatre sources se cumulent, et la troisième est la plus souvent oubliée.
- Le code du dépôt, à la référence checkoutée. Laquelle exactement ? Un
ref:pointant vers la HEAD d'une pull request change tout. - Les actions tierces, qui sont du code exécuté avec les mêmes droits que vos propres étapes.
- Les dépendances installées pendant le job. Un
npm ciexécute les scripts d'installation des paquets, y compris transitifs. - Les outils téléchargés par une action, dont la version n'est pas toujours figée.
3. Sur quelle machine ?
Section intitulée « 3. Sur quelle machine ? »Un runner hébergé par GitHub est une machine jetable, sur l'internet public, détruite après le job. Un runner auto-hébergé est votre infrastructure, avec vos accès réseau, et il persiste sauf configuration contraire.
La question à se poser n'est pas « ce runner est-il durci », mais « que joint cette machine » : bases internes, registres, API d'administration. Le cloisonnement par runner groups traite ce point en détail.
4. Avec quel jeton ?
Section intitulée « 4. Avec quel jeton ? »Le GITHUB_TOKEN du job, avec les permissions déclarées. La question utile est
de traduire chaque permission en capacité offensive : contents: write
permet de modifier le code, donc d'ajouter un workflow, donc de persister.
packages: write permet de publier une version piégée sous votre nom.
id-token: write permet d'obtenir un jeton cloud, si une trust policy l'accepte.
5. Quels secrets ?
Section intitulée « 5. Quels secrets ? »Listez ce qui est réellement présent dans l'environnement du job, pas ce que le workflow est censé utiliser. Un secret d'environnement n'est délivré qu'après validation des règles de protection ; un secret de dépôt est là dès le démarrage du job, qu'on s'en serve ou non.
Pour chaque secret, la question qui compte n'est pas « est-il masqué » mais « qu'ouvre-t-il, et combien de temps ». Un jeton statique de production vaut infiniment plus qu'un jeton OIDC de dix minutes restreint à un dépôt.
6. Vers où peut-il émettre ?
Section intitulée « 6. Vers où peut-il émettre ? »Toute exfiltration a besoin d'un canal de sortie. Par défaut, un runner joint n'importe quelle adresse. Restreindre les destinations autorisées ne prévient pas la compromission, mais la rend stérile : le secret volé ne part nulle part, et la tentative devient un échec de job, donc un signal.
7. Quel artefact, pour qui ?
Section intitulée « 7. Quel artefact, pour qui ? »C'est la question de la propagation, et celle qu'on oublie le plus. Un workflow compromis qui ne produit rien nuit à un dépôt. Un workflow compromis qui publie une image consommée par quarante services, ou une action réutilisée par toute l'organisation, transforme un incident local en incident de chaîne d'approvisionnement.
Repérer la frontière de confiance
Section intitulée « Repérer la frontière de confiance »La notion centrale tient en une phrase : la frontière de confiance est l'endroit où une donnée que vous ne contrôlez pas entre dans un contexte que vous contrôlez. Un workflow dangereux est presque toujours un workflow où cette frontière est franchie sans qu'on s'en aperçoive.
Les entrées non fiables sont peu nombreuses et se reconnaissent :
- le contenu d'une pull request de fork, code et fichiers de configuration ;
- les champs libres remplis par un tiers : titre et corps d'issue ou de pull request, commentaire, nom de branche, message de commit ;
- les entrées de
workflow_dispatch, saisies par un humain ; - les artefacts d'une autre exécution, dans un workflow déclenché par
workflow_run; - les réponses d'API externes consommées pendant le job.
Le test se formule ainsi : cette valeur peut-elle être choisie par quelqu'un qui n'a pas le droit d'écrire sur le dépôt ? Si oui, elle est non fiable, et tout ce qu'elle atteint est suspect.
Le rayon d'explosion, plus utile que la probabilité
Section intitulée « Le rayon d'explosion, plus utile que la probabilité »Classer les risques par probabilité conduit à repousser indéfiniment les scénarios rares. Or en sécurité de chaîne d'approvisionnement, les incidents marquants sont précisément des événements qu'on jugeait improbables. Le classement par rayon d'explosion est plus opérant : il demande ce que coûte l'incident, pas sa fréquence.
| Rayon | Ce qui est atteint | Exemple |
|---|---|---|
| Le job | Une exécution, rien ne persiste | Un runner hébergé sans secret |
| Le dépôt | Code, releases, paquets de ce dépôt | contents: write détourné |
| L'organisation | Plusieurs dépôts, secrets partagés | Secret d'organisation exfiltré |
| Les consommateurs | Les utilisateurs de vos artefacts | Image ou action publiée piégée |
| L'infrastructure | Réseau interne, production | Runner auto-hébergé compromis |
Les deux dernières lignes justifient à elles seules l'exercice : ce sont celles où la remédiation dépasse largement votre dépôt, et où il faut prévenir des tiers.
Un exemple déroulé
Section intitulée « Un exemple déroulé »Prenons un workflow de publication réaliste : déclenché à la publication d'une release, il construit une image, la pousse sur un registre, l'atteste et la signe.
| Question | Réponse | Verdict |
|---|---|---|
| Qui déclenche | Publication d'une release, donc les mainteneurs | Population restreinte |
| Quel code | Le dépôt au tag, plus sept actions tierces épinglées par SHA | Surface tierce réelle |
| Quelle machine | Runner hébergé, jetable | Faible |
| Quel jeton | packages: write, id-token: write, attestations: write, contents: write | Élevé, mais justifié |
| Quels secrets | Le GITHUB_TOKEN du job, aucun secret statique | Bon |
| Sortie réseau | Non restreinte | Point faible |
| Artefact | Image publique consommée par des tiers | Rayon maximal |
La lecture croisée donne la priorité immédiatement, et elle n'est pas celle qu'on attendait. Le risque n'est ni le déclencheur, ni le jeton : c'est la combinaison de la dernière ligne et de l'avant-dernière. Une action tierce compromise parmi les sept dispose d'un canal de sortie libre et d'un artefact à large diffusion.
Les deux corrections prioritaires en découlent : restreindre le trafic sortant du job de publication, et maintenir les épinglages pour réduire la fenêtre pendant laquelle une action compromise reste en place. Le durcissement des permissions, qui aurait été le réflexe, arrive après.
Par où commencer, et quand recommencer
Section intitulée « Par où commencer, et quand recommencer »Modéliser tous les workflows d'une organisation n'a pas de sens. Trois critères désignent ceux qui le méritent, et un workflow qui en cumule deux passe en tête.
-
Il est déclenchable par un tiers :
pull_requestsur dépôt public,pull_request_target,issue_comment. -
Il dispose de secrets ou de permissions d'écriture : publication, déploiement, signature.
-
Il produit quelque chose que d'autres consomment : image, paquet, action réutilisable, workflow réutilisable.
L'exercice se refait sur événement, pas sur calendrier. Quatre changements invalident une modélisation existante : l'ajout d'un déclencheur, l'ajout d'un secret ou d'une permission, le passage à un runner auto-hébergé, et le fait qu'un artefact gagne des consommateurs. Les trois premiers se voient dans le diff, le quatrième non, et c'est celui qui transforme silencieusement un risque local en risque de chaîne.
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
À retenir
Section intitulée « À retenir »- Un workflow peut passer tous les scanners et rester dangereux : ils voient des motifs connus, pas ce que vos secrets ouvrent ni où vos runners sont branchés.
- La méthode tient en sept questions qui suivent le trajet d'une attaque : déclencheur, code, machine, jeton, secrets, sortie réseau, artefact.
- La frontière de confiance est l'endroit où une donnée choisie par quelqu'un sans droit d'écriture entre dans un contexte privilégié.
- Classez par rayon d'explosion plutôt que par probabilité : les incidents marquants étaient tous jugés improbables.
- Un workflow sans canal de sortie rend une compromission stérile : le secret volé ne part nulle part et la tentative devient un signal.
- La question la plus oubliée est la septième : qui consomme l'artefact produit, et donc jusqu'où l'incident se propage.
- Modélisez en priorité les workflows déclenchables par un tiers, porteurs de secrets ou producteurs d'artefacts diffusés, et refaites l'exercice sur événement, pas à date fixe.
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Sécuriser pull_request_target : Le déclencheur qui franchit la frontière de confiance par construction, et les gardes qui la rétablissent.
- OIDC : authentification sans secrets : Réduire la valeur de la cinquième question en remplaçant les jetons statiques par des jetons de quelques minutes.
- Checklist sécurité : Le passage systématique qui transforme les conclusions de cette modélisation en points de contrôle avant fusion.