Catégorie : CI/CD

GitHub Actions, sécurité des pipelines et supply chain : les changements CI/CD à connaître et les réglages à activer dans tes workflows.

  • GitHub Public Monitoring : triage et vérification pour les secrets qui fuitent

    GitHub Public Monitoring : triage et vérification pour les secrets qui fuitent

    Un stagiaire pousse par erreur un fichier .env dans un fork public de ton repo interne. Trois minutes plus tard, un bot scanne la clé AWS qu’il contient et teste si elle fonctionne encore. C’est à peu près le scénario que GitHub cherche à raccourcir avec Public Monitoring, sa fonctionnalité de détection de secrets exposés en dehors de tes propres dépôts privés — et qui vient de gagner un vrai outil de triage le 23 octobre 2026.

    Ce que Public Monitoring surveille (et ce qu’il ne surveille pas)

    Lancée en préversion publique le 1er juillet 2026, Public Monitoring scanne en continu la surface publique de github.com : contenu Git, commentaires de pull request, issues. Elle ne touche jamais aux dépôts privés — GitHub est explicite là-dessus dans l’annonce d’origine. L’idée n’est pas de remplacer le secret scanning classique sur tes propres repos, mais de repérer ce qui a fuité ailleurs : un fork personnel oublié, un gist, le dépôt public d’un ancien contributeur qui a copié-collé un bout de code avec un token dedans.

    L’attribution à ton entreprise se fait de deux façons. La première, par appartenance : si le compte qui a commité est membre de ton organisation GitHub, la fuite remonte automatiquement. La seconde, plus intéressante, par domaine vérifié : si l’e-mail associé au commit utilise un domaine que ton organisation a vérifié, la fuite est rattachée même si le compte GitHub n’a jamais été ajouté à l’entreprise — typiquement un compte personnel qu’un développeur utilise avec son adresse pro. C’est ce deuxième mécanisme qui couvre le vrai angle mort : les devs qui bossent sur leurs propres projets open source avec leur mail d’entreprise, sans que personne au sein de la boîte le sache.

    Les nouveautés du 23 octobre : on passe du simple radar à un vrai outil de travail

    Jusqu’ici, Public Monitoring se contentait de remonter une alerte dans le dashboard de sécurité de l’entreprise, sans grand-chose pour la gérer au quotidien. La mise à jour du 23 octobre change ça sur quatre points.

    Triage depuis le dashboard

    Les admins d’entreprise et les security managers peuvent désormais fermer une alerte (Ignorée ou Corrigée, avec un commentaire optionnel), la rouvrir, et consulter l’historique complet des actions. Le filtrage par dépôt, committer, type de secret, méthode d’attribution et statut rend enfin gérable une liste qui, sur une grosse organisation, peut vite compter des dizaines d’entrées.

    Vérification de validité en continu

    Chaque alerte affiche désormais un statut — Active, Inactive ou Inconnu — basé sur une vérification automatique et permanente de la validité du token, pour les fournisseurs supportés. Concrètement : plus besoin de tester toi-même si la clé AWS qui a fuité est encore valide avant de paniquer ou de l’ignorer.

    API REST et webhook d’entreprise

    Le nouvel endpoint GET /enterprises/{enterprise}/secret-scanning/public-monitoring-alerts expose les métadonnées complètes (type de secret, attribution, emplacement d’exposition). Exemple d’appel :

    curl -H "Authorization: Bearer $GH_ENTERPRISE_TOKEN" \
      -H "Accept: application/vnd.github+json" \
      "https://api.github.com/enterprises/ctrl-alt-prod/secret-scanning/public-monitoring-alerts?state=open"

    Et pour être notifié en temps réel sans avoir à poller l’API, l’événement webhook secret_scanning_public_monitoring_alert se souscrit au niveau de l’entreprise — de quoi brancher ça directement sur ton canal d’astreinte plutôt que de compter sur quelqu’un qui pense à aller vérifier le dashboard.

    Ce que fermer une alerte NE fait PAS

    Un point que GitHub précise noir sur blanc dans son changelog et qui mérite d’être répété : passer une alerte en « Corrigée » ne révoque rien et ne supprime rien du dépôt public concerné. Ça change seulement son statut dans ton tableau de bord d’entreprise. La clé AWS qui a fuité reste valide et visible publiquement jusqu’à ce que quelqu’un la révoque réellement côté fournisseur et nettoie l’historique Git si besoin. Le triage organise le travail, il ne le fait pas à ta place.

    Et il y a un angle mort plus sérieux que celui-là, pointé par StepSecurity dans son analyse de la fonctionnalité : Public Monitoring ne voit que ce qui finit publiquement visible sur github.com. Si un secret est exfiltré vers une infrastructure contrôlée par l’attaquant — exactement le mode opératoire des campagnes TeamPCP et GhostAction documentées cette année — la fonctionnalité ne le détecte jamais, puisqu’il n’y a rien à scanner sur GitHub. Les logs d’exécution des workflows Actions, eux, ne sont mentionnés nulle part dans la documentation de couverture : à traiter comme hors périmètre jusqu’à preuve du contraire.

    Disponible pour qui, à quel coût

    Public Monitoring reste en préversion publique, réservée à GitHub Enterprise Cloud, et incluse sans coût supplémentaire si tu as déjà une licence GitHub Advanced Security ou GitHub Secret Protection. Depuis le 22 octobre, elle couvre aussi les clients Enterprise Cloud avec data residency — une case qui restait vide depuis le lancement de juillet.

    Ce que ça change concrètement pour ton équipe

    La vraie valeur de cette mise à jour n’est pas la détection elle-même — elle existait déjà depuis juillet — mais le fait qu’elle devienne enfin exploitable en routine. Avant le 23 octobre, une alerte Public Monitoring finissait soit ignorée dans un coin du dashboard, soit traitée à la main sans trace de qui avait fait quoi. Avec le triage, l’historique et le webhook, tu peux enfin la faire entrer dans un vrai processus d’astreinte : réception en temps réel, vérification de validité automatique pour prioriser, et une trace d’audit pour savoir qui a fermé quoi et pourquoi.

    Ceci dit, ça reste de la détection après coup. Si ton équipe pousse régulièrement des secrets par erreur, la vraie correction est en amont — un hook de push protection qui bloque le commit avant qu’il parte, pas un dashboard qui te prévient après qu’il soit déjà public. Public Monitoring est un excellent filet de sécurité pour les angles morts (forks, comptes personnels, anciens contributeurs) ; ce n’est pas une raison de relâcher la discipline sur tes propres dépôts.

    FAQ

    Public Monitoring scanne-t-il mes dépôts privés ?

    Non, jamais. GitHub l’indique explicitement : seule la surface publique de github.com est couverte (contenu Git, PR, issues).

    Faut-il une configuration particulière pour l’activer ?

    Non — les propriétaires d’entreprise et les security managers l’activent depuis l’onglet Security, sans paramétrage supplémentaire au niveau des dépôts individuels.

    Que se passe-t-il si je ferme une alerte par erreur ?

    Tu peux la rouvrir à tout moment depuis le dashboard — l’historique garde la trace de chaque changement d’état, donc rien n’est perdu.

    La vérification de validité fonctionne-t-elle pour tous les types de secrets ?

    Non, uniquement pour les fournisseurs supportés par le mécanisme de validity checking de GitHub. Pour les autres, l’alerte reste au statut « Inconnu ».

    En pratique

    Si ton organisation a déjà GitHub Advanced Security ou Secret Protection, active Public Monitoring cette semaine et branche le webhook sur ton outil d’astreinte plutôt que de laisser quelqu’un surveiller le dashboard à la main. Et pendant que tu y es, vérifie que la protection de ta chaîne de dépendances npm en CI est aussi activée, et que ton cache GitHub Actions ne traîne pas une vieille faille de cache poisoning — les trois couvrent des angles morts différents de la même histoire de supply chain.

  • GitHub Package Firewall : stopper les malwares npm en pleine CI

    GitHub Package Firewall : stopper les malwares npm en pleine CI

    Le 17 juin 2026, un mainteneur npm compromis publie mastra@1.13.1 depuis une adresse Tutamail anonyme, en dehors du pipeline GitHub Actions habituel. Le seul changement : une dépendance ajoutée, easy-day-js, un typosquat de la bibliothèque dayjs. Résultat : 140 packages de l’écosystème @mastra touchés, un script postinstall qui désactive la vérification TLS, télécharge une charge de second niveau et installe une persistance sur Windows, macOS et Linux. Microsoft attribue l’attaque à Sapphire Sleet, un groupe nord-coréen, avec un niveau de confiance élevé.

    C’est ce genre de scénario que GitHub Package Firewall, passé en preview publique le 20 octobre 2026, essaie d’intercepter avant qu’il n’atteigne tes runners. Pas en analysant le code après coup, mais en se plaçant entre tes endpoints et le registre npm, au moment même où le `npm install` part chercher ses dépendances.

    Ce que fait réellement le pare-feu

    Le principe est simple sur le papier. Tu configures tes runners Actions, tes postes de développement ou tes agents de code pour router leurs requêtes npm — métadonnées de package comme téléchargements effectifs — à travers le pare-feu plutôt que directement vers la registry publique. Chaque requête est alors évaluée contre une politique que tu définis au niveau de l’organisation : une période de cooldown qui bloque les versions trop récentes (le temps que la communauté détecte une éventuelle charge malveillante), une vérification croisée avec la GitHub Advisory Database, et des contrôles de chaîne d’approvisionnement comme la détection d’une attestation de provenance qui régresse entre deux versions.

    Si un package légitime se retrouve bloqué par erreur, tu peux demander une exception via un workflow similaire à celui des autres fonctionnalités GitHub Advanced Security — pas de blocage définitif sans recours.

    Ce qui manque encore

    Deux limites à garder en tête avant de t’enthousiasmer. D’abord, seul l’écosystème npm est couvert pour l’instant — rien pour PyPI, NuGet ou les modules Terraform, alors que les attaques par typosquat touchent tous les registries. Ensuite, et c’est le point le plus important : le pare-feu ne protège que le trafic qui passe réellement par lui. Un runner mal configuré, un script qui pointe en dur vers registry.npmjs.org, ou un développeur qui installe en local sans passer par le proxy d’entreprise, contournent entièrement la protection. Ce n’est pas un défaut caché, GitHub le dit explicitement dans sa documentation : la fonctionnalité dépend de l’endpoint qui joue le jeu.

    Disponible pour tous les clients GitHub Enterprise Cloud (y compris avec data residency), gratuit pendant la preview, facturé à l’usage comme Actions à la disponibilité générale — sans date ni tarif annoncés pour l’instant.

    Pourquoi ça a du sens maintenant

    Le cas Mastra n’est pas isolé. TanStack, Jscrambler, et une bonne partie du calendrier 2026 des compromissions npm suivent le même schéma, déjà détaillé dans notre tour d’horizon des attaques supply chain CI/CD de 2026 : un compte mainteneur pris, un typosquat ou une dépendance ajoutée discrètement, un hook postinstall qui exfiltre des tokens avant même que le code applicatif ne tourne. C’est exactement le moment où un pare-feu en amont du téléchargement a le plus de valeur — contrairement à un scan de code qui arrive après coup, quand le malware a déjà eu l’occasion de s’exécuter.

    Ça rejoint la logique derrière les workflow lockfiles GitHub Actions, publiés quatre jours plus tôt : les deux mécanismes attaquent le même problème — une chaîne de dépendances qui change sous tes pieds sans que tu t’en rendes compte — mais à des niveaux différents. Les lockfiles verrouillent le graphe de dépendances de tes workflows Actions eux-mêmes ; le pare-feu filtre ce que npm va chercher pendant l’exécution de ton build. Les deux ensemble, pas l’un à la place de l’autre.

    En attendant que le pare-feu couvre d’autres écosystèmes, la mitigation la plus simple reste à la portée de tout le monde dès aujourd’hui : npm install --ignore-scripts désactive l’exécution de tout hook postinstall, au prix de devoir parfois relancer manuellement un build natif pour les packages qui en ont réellement besoin.

    # Installer sans exécuter les scripts de cycle de vie
    npm install --ignore-scripts
    
    # Vérifier après coup si une dépendance a tenté d'en profiter
    npm config get ignore-scripts

    FAQ

    Le pare-feu remplace-t-il un scanner de dépendances type Dependabot ou Snyk ?

    Non. Dependabot et les scanners SCA analysent ton code et tes manifestes de dépendances pour repérer des vulnérabilités connues. Le pare-feu, lui, agit en amont, au moment où npm va chercher un package sur le réseau — il bloque avant le téléchargement, pas après coup sur une base déjà installée.

    Faut-il GitHub Enterprise pour en profiter ?

    Oui, c’est réservé aux clients GitHub Enterprise Cloud à ce stade (data residency incluse). Rien n’indique pour l’instant une disponibilité sur les plans Team ou Pro.

    Si je n’ai pas Enterprise, que faire en attendant ?

    Verrouille tes dépendances avec un fichier de lock à jour, désactive les scripts de cycle de vie par défaut sur les environnements CI qui n’en ont pas besoin, et surveille les alertes de la GitHub Advisory Database sur tes dépôts — c’est la même base que le pare-feu interroge en coulisses.

    Pour la suite

    Le pare-feu npm est un bon réflexe défense-en-profondeur, pas une solution miracle : il ne vaut que ce que vaut le routage réseau derrière lui. Si tu es sur GitHub Enterprise, active-le en mode non bloquant d’abord pour calibrer la politique de cooldown sans casser tes builds, puis passe en application stricte une fois que tu as confiance dans les faux positifs. Et quel que soit ton plan GitHub, prends cinq minutes pour vérifier que tes pipelines n’installent pas déjà des dépendances avec des scripts de cycle de vie que tu n’as jamais auditées.

  • Lockfiles GitHub Actions : verrouille enfin tes dépendances

    Lockfiles GitHub Actions : verrouille enfin tes dépendances

    Le 14 octobre 2026, GitHub a publié en preview publique un mécanisme qui manquait cruellement à Actions depuis ses débuts : un vrai lockfile. Jusqu’ici, épingler une action sur un SHA de commit restait une discipline manuelle, facile à oublier sur une dépendance transitive planquée dans une action composite. Les actions.lock changent la donne : ils figent tout le graphe de dépendances d’un workflow, pas seulement ce que tu écris toi-même dans le YAML.

    Si tu as lu notre article sur les immutable actions et la fermeture de la faille tj-actions, tu sais déjà que GitHub avance par étapes sur la sécurité de la chaîne d’approvisionnement Actions. Les lockfiles sont la pièce suivante : là où les immutable actions sécurisent la distribution côté mainteneur, les lockfiles verrouillent la consommation côté utilisateur.

    Le problème que le SHA-pinning seul ne couvre pas

    Épingler actions/checkout@a1b2c3d... plutôt que actions/checkout@v4 protège contre une réécriture de tag. Mais une action composite peut elle-même appeler d’autres actions en interne, sans que tu le voies dans ton propre workflow. Si cette dépendance de second niveau n’est pas épinglée par son mainteneur, ton pinning de surface ne sert à rien : le code qui s’exécute réellement peut changer sous tes pieds.

    C’est exactement le schéma de l’attaque tj-actions de mars 2025, qu’on a détaillée dans notre article sur les leçons supply chain : environ 23 000 dépôts touchés par une seule action compromise, propagée via des dépendances en cascade. Le pinning manuel ne scale juste pas sur un graphe de dépendances profond.

    Ce qu’un lockfile GitHub Actions verrouille concrètement

    Le fichier généré s’appelle .github/workflows/actions.lock, en schéma v0.0.2 (encore amené à évoluer, le projet est pré-1.0). Il contient deux sections : workflows, qui associe chaque fichier de workflow aux actions et reusable workflows qu’il référence, et dependencies, qui enregistre pour chaque référence le tag (ref), le SHA de commit résolu, et les identifiants numériques owner_id/repo_id — utiles pour détecter un renommage ou une redirection de dépôt, un vecteur d’attaque réel.

    Trois niveaux sont couverts, et c’est là que ça dépasse le simple pinning :

    • Actions directes : tag et SHA résolu enregistrés côte à côte.
    • Actions transitives : pour une action composite, tout le graphe de dépendances imbriqué est verrouillé dans le lockfile de ton propre dépôt.
    • Reusable workflows : ton lockfile épingle le commit du fichier de workflow réutilisable appelé, mais les dépendances internes de ce workflow réutilisable restent gouvernées par le lockfile du dépôt qui le définit — raison de plus pour onboarder en priorité les dépôts qui hébergent des workflows partagés.

    À l’exécution, Actions lance le commit verrouillé, point final — peu importe où pointe le tag amont au moment du run. Les politiques « allowed actions » sont évaluées contre ce commit verrouillé, pas contre le tag.

    Générer et vérifier le lockfile

    L’outillage passe par une extension GitHub CLI :

    gh extension install github/gh-actions-lock
    gh actions-lock

    Lancée depuis la racine du dépôt, cette commande scanne .github/workflows/ et écrit le lockfile. Un scan complet du dossier retire aussi les entrées des workflows supprimés ; tu peux aussi cibler un workflow précis pour ne toucher que celui-là.

    Deux modes de vérification, pour deux contextes différents :

    • gh actions-lock --verify contrôle que le lockfile est à jour sans rien modifier — pensé pour un job de CI sur une pull request.
    • gh actions-lock --verify-local --no-fix tourne hors ligne, pour un hook pre-commit. Il ne vérifie que la complétude structurelle, pas la validité des pins côté GitHub.

    Dependabot s’intègre à la mécanique : quand il bump une action déjà onboardée, il régénère l’entrée correspondante dans la même pull request. Il ne crée en revanche pas d’entrée pour un workflow qui n’a encore aucune couverture — l’onboarding initial reste à faire manuellement.

    La politique « Require lockfile » côté administration

    Pour les organisations qui veulent imposer la pratique plutôt que la suggérer, une politique « Require lockfile » existe en parallèle, elle aussi en preview publique, réglable au niveau entreprise, organisation ou dépôt. Deux modes : Evaluate, disponible uniquement sur GitHub Enterprise, qui remonte dans Policy insights ce qui serait bloqué sans réellement bloquer — et Active, qui bloque pour de vrai l’exécution des workflows ciblés dès qu’une dépendance d’action n’est pas couverte par le lockfile du dépôt.

    La documentation officielle recommande un déploiement en quatre étapes plutôt qu’un passage en force : pilote sur quelques dépôts, automatisation de la maintenance des lockfiles, renforcement de la revue de code via CODEOWNERS sur actions.lock, puis activation large. Vu le nombre de dépôts qui n’ont encore aucun lockfile, basculer direct en mode Active sans ce palier casserait des pipelines pour de mauvaises raisons.

    Ce que ça ne règle pas

    Un lockfile fige quelle révision s’exécute, pas si cette révision est saine. Verrouiller une action compromise revient juste à garantir que c’est toujours la version compromise qui tourne — la revue du code tiers reste nécessaire, lockfile ou pas. Et comme l’ensemble CLI/schéma est pré-1.0, les flags et le format peuvent encore changer avant stabilisation. GitHub Enterprise Server n’est pour l’instant pas couvert : seul Enterprise Cloud (y compris avec data residency) a accès à la fonctionnalité.

    FAQ

    Faut-il abandonner le SHA-pinning manuel si on adopte les lockfiles ?

    Non. Les politiques de SHA-pinning existantes peuvent coexister : pour une dépendance verrouillée, l’exigence de SHA est simplement vérifiée contre le commit du lockfile plutôt que contre le tag.

    Est-ce que ça marche sur GitHub Enterprise Server ?

    Pas pour l’instant. La preview publique du 14 octobre 2026 couvre uniquement GitHub Enterprise Cloud, y compris les configurations avec data residency.

    Que se passe-t-il si un mainteneur renomme son dépôt d’action ?

    Le lockfile stocke owner_id et repo_id, vérifiés à l’exécution — ce qui permet de détecter un renommage ou une redirection, plutôt qu’un simple suivi par nom qui se ferait avoir silencieusement.

    Passer à l’action

    Si tu gères plus d’une poignée de workflows avec des actions tierces, installer gh-actions-lock et lancer un premier gh actions-lock en mode diagnostic coûte dix minutes et te donne une photo exacte de ce qui tourne vraiment dans tes pipelines. Garde la politique « Require lockfile » en mode Evaluate le temps d’onboarder tes dépôts les plus critiques — l’activer trop tôt reviendrait à bloquer tes propres builds pour une couverture encore partielle.

  • Immutable Actions : GitHub ferme la faille tj-actions

    Immutable Actions : GitHub ferme la faille tj-actions

    Le 14 mars 2025, l’action GitHub tj-actions/changed-files a été compromise : un tag réécrit a pointé vers du code qui exfiltrait les secrets des runners vers les logs publics. Environ 23 000 dépôts l’utilisaient. Pas besoin d’exploiter une faille applicative — il suffisait de contrôler un tag Git pour réécrire silencieusement toutes les références qui pointaient vers lui.

    Dix-huit mois plus tard, GitHub a généralisé une réponse structurelle à ce type d’attaque : les immutable actions. Le principe est simple à énoncer, un peu moins simple à mettre en œuvre correctement — et surtout, ça ne protège personne tant que tu n’as pas changé quelque chose dans tes workflows.

    Ce qui s’est cassé avec tj-actions/changed-files

    Référencer une action par un tag comme @v45 revient à faire confiance à ce que ce tag désigne au moment de l’exécution, pas au moment où tu as écrit ton workflow. Un tag Git n’est qu’un pointeur : son propriétaire peut le faire pointer ailleurs sans que personne ne le remarque. C’est exactement ce qui s’est produit avec tj-actions/changed-files (CVE-2025-30066) : les tags de version ont été réécrits pour exécuter un script qui dumpait la mémoire des runners dans les logs publics, à la recherche de secrets.

    Le pinning par SHA de commit complet (@a1b2c3d...) protège contre ce scénario précis. Mais il a une limite que peu de gens vérifient : une action composite peut elle-même appeler d’autres actions, et ces dépendances-là restent mutables même si l’action de premier niveau est épinglée. Tu peux donc être rigoureux sur ton propre workflow et rester exposé via une couche que tu ne vois jamais.

    Comment fonctionnent les immutable actions

    Depuis leur généralisation (suivie publiquement sur la roadmap GitHub), une action publiée en version immuable n’est plus distribuée comme un simple tag Git : elle devient un artefact OCI, stocké dans GitHub Packages et adressé par un digest de contenu. Ce digest ne change jamais pour une version donnée — toute correction passe obligatoirement par une nouvelle version.

    Concrètement, à l’exécution d’un job, le runner résout la version demandée, récupère le digest attendu, et le compare à celui qu’il vient de télécharger avant d’exécuter le moindre code de l’action. Un écart interrompt le job. Les actions composites sont dépliées récursivement, donc le graphe complet des dépendances — y compris celles que tu ne déclares jamais toi-même — devient vérifiable de la même façon.

    Et le pinning par SHA, alors ?

    Il reste utile, notamment pour les actions qui n’ont pas encore migré vers la distribution immuable — ce qui concerne la grande majorité des dizaines de milliers d’actions publiées sur le Marketplace. On avait détaillé les bonnes pratiques de pinning juste après l’incident tj-actions, dans cet article : elles restent valables, les deux mécanismes se complètent plutôt qu’ils ne se remplacent.

    Publier une action immuable (côté mainteneur)

    Si tu maintiens une action, le passage se fait via le workflow dédié actions/publish-immutable-action, qui prend ton code existant et le publie dans GitHub Packages sous forme d’image versionnée, selon un modèle build → package → publish entièrement automatisé. Côté utilisateurs de ton action, rien ne change dans leur syntaxe : une référence par tag (@v3) continue de fonctionner, elle pointe simplement désormais vers une version packagée et vérifiée plutôt que vers un tag Git classique. Seules les références par SHA de commit brut ou par nom de branche doivent migrer vers une référence de version.

    Ce que la généralisation ne fait pas automatiquement

    C’est le point que la plupart des annonces passent sous silence : la disponibilité de la fonctionnalité n’oblige personne à l’utiliser, et GitHub ne propose aujourd’hui aucune politique native pour l’exiger. Tu peux avoir des centaines de workflows qui référencent encore des actions mutables sans qu’aucun signal ne te le dise — sauf à le vérifier toi-même.

    Une solution communautaire répandue consiste à transformer cette vérification en required workflow, via l’action joshjohanning/ensure-immutable-actions (décrite en détail ici). Elle classe chaque action référencée dans un workflow en trois catégories — première partie (actions/*, github/*), immuable (release immuable ou SHA complet), ou mutable — et fait échouer la vérification si une action mutable est détectée :

    name: Check Action Immutability
    on:
      pull_request:
    permissions:
      contents: read
    jobs:
      check-immutable:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v6
          - name: Ensure immutable actions
            uses: joshjohanning/ensure-immutable-actions@v2

    Ce workflow se déclare ensuite comme obligatoire dans un ruleset d’organisation (Settings → Rules → Rulesets → Require workflows to pass before merging), en mode actif pour bloquer les PR non conformes, ou en mode évaluation pour observer avant de durcir la règle. L’intérêt de ce contrôle continu : même si un mainteneur désactive l’immuabilité sur sa prochaine release, la PR suivante qui référence cette version mutable se fait signaler.

    Ce que ça ne règle pas

    L’immuabilité verrouille une version publiée ; elle ne dit rien de ce qu’un mainteneur légitime décide de publier ensuite. Si son compte est compromis, ou s’il publie délibérément une nouvelle version piégée, cette nouvelle version sera immuable elle aussi — et tout aussi dangereuse. La revue de code et le scan de dépendances restent nécessaires, l’immuabilité ne les remplace pas.

    Deux autres limites à connaître : la signature et l’attestation de provenance (via Sigstore), ainsi que le scan anti-malware des actions publiées, sont présentées comme des évolutions à venir, pas comme des protections déjà actives aujourd’hui. Et une grande partie des actions les moins utilisées du Marketplace ne migreront probablement jamais, faute de maintenance active — ta politique de blocage doit rester la solution de repli pour ces cas-là, pas l’immuabilité seule.

    FAQ

    Les immutable actions remplacent-elles le pinning par SHA ?

    Non. Elles couvrent un angle mort du pinning par SHA (les dépendances internes des actions composites), mais tant qu’une action n’a pas migré, le SHA reste ta seule protection contre la réécriture de tag.

    Dois-je changer la syntaxe de mes workflows existants ?

    Pas si tu références déjà les actions par tag de version (@v4, par exemple). Seules les références par SHA de commit brut ou par branche nécessitent une mise à jour vers une version sémantique.

    Comment savoir si une action que j’utilise est déjà immuable ?

    Aucune commande native ne le liste encore de façon exhaustive ; des outils tiers comme le workflow ensure-immutable-actions ci-dessus font ce travail de vérification à ta place.

    Passe à l’action

    Commence par vérifier si les actions tierces les plus critiques de ton organisation — celles qui touchent au déploiement ou à la publication d’artefacts — ont déjà une version immuable disponible. Si oui, mets à jour tes références de version. Si non, le pinning par SHA reste ta meilleure protection en attendant. Et dans tous les cas, un required workflow qui vérifie ça automatiquement t’évite de devoir y repenser à chaque nouveau pipeline.

  • GitHub Actions : tes runs et logs s’effacent plus vite depuis le 1er octobre

    GitHub Actions : tes runs et logs s’effacent plus vite depuis le 1er octobre

    Depuis le 1er octobre 2026, tes checks, exécutions de workflow et statuts GitHub Actions ne vivent plus indéfiniment : ils suivent désormais la même politique de rétention que les artefacts et les logs. Si tu n’as jamais touché à ce réglage, la limite par défaut tombe à 90 jours — et pour les dépôts publics, c’est un plafond dur qu’aucune configuration ne permet de dépasser.

    Ce qui a changé le 1er octobre

    Avant ce changement, les checks, les runs de workflow et les statuts créés par Actions (et par des applications tierces) pouvaient rester visibles plus de 400 jours, indépendamment du réglage de rétention des artefacts et des logs. GitHub a annoncé l’alignement de ces trois types de données sur cette même politique le 27 août 2026, avec une bascule confirmée effective le 1er octobre. Le paramètre dans les réglages du dépôt a d’ailleurs été renommé pour refléter ce périmètre élargi : il s’appelle désormais « Check, workflow run, status, artifact and log retention » plutôt que de ne mentionner qu’artefacts et logs.

    La raison donnée par GitHub est double : simplifier l’administration (un seul réglage à surveiller au lieu de plusieurs politiques implicites) et réduire la facture de stockage pour les dépôts qui, sans le savoir, conservaient des données bien au-delà de ce qu’ils avaient configuré pour les artefacts.

    Les chiffres à retenir

    La rétention se configure à trois niveaux — dépôt, organisation, entreprise — chacun pouvant resserrer mais jamais dépasser le plafond fixé au niveau supérieur. Deux chiffres à garder en tête : 90 jours par défaut, et 90 jours de plafond absolu pour les dépôts publics, quel que soit le réglage souhaité au niveau dépôt. Un dépôt privé peut viser plus large si son organisation l’autorise, un dépôt public open source non.

    L’impact concret pour toi

    Deux conséquences directes. D’abord, côté conformité et audit : si tu t’appuies sur l’historique des checks ou des statuts de commit comme preuve qu’une PR a bien passé tes contrôles qualité à une date donnée, cette preuve disparaît désormais au bout de 90 jours sauf configuration explicite plus large. Ensuite, côté facturation : artefacts et logs comptent dans le stockage Actions facturable, donc un repository qui conservait ses données plus longtemps que prévu par erreur devrait voir sa facture de stockage baisser mécaniquement.

    Ce qui est supprimé ne revient pas. GitHub est explicite là-dessus : les enregistrements qui dépassaient déjà la période configurée au moment de la bascule ont été nettoyés automatiquement, sans fenêtre de rattrapage.

    Comment vérifier et ajuster ta configuration

    Le réglage se trouve dans Settings > Actions > General de chaque dépôt (ou au niveau organisation/entreprise pour un contrôle centralisé), documenté sur la page officielle Managing GitHub Actions settings for a repository. Trois réflexes avant de passer à autre chose :

    • Vérifie la rétention actuellement configurée sur tes dépôts critiques — beaucoup d’équipes n’y ont jamais touché depuis la création du dépôt.
    • Si tu as besoin de conserver une preuve d’exécution au-delà de 90 jours (audit SOC 2, exigence contractuelle), augmente la rétention jusqu’au plafond autorisé par ton organisation, ou exporte régulièrement les données vers un stockage externe via l’API Actions.
    • Pour un dépôt public qui doit prouver sa conformité sur le long terme, ne compte plus sur la rétention native : archive toi-même les résultats de checks importants (par exemple via un job qui pousse un résumé signé vers un bucket ou un dépôt séparé).

    FAQ

    Puis-je récupérer des runs déjà supprimés par ce changement ?

    Non. GitHub est catégorique : les enregistrements nettoyés ne sont pas restaurés, qu’ils aient été supprimés avant ou après le 1er octobre.

    Ce changement affecte-t-il les workflows en cours d’exécution ?

    Non, seuls les checks, runs et statuts déjà terminés et dépassant la période de rétention configurée sont concernés.

    Un dépôt privé peut-il dépasser 90 jours de rétention ?

    Oui, si l’organisation ou l’entreprise qui l’héberge autorise une limite plus élevée. Le plafond de 90 jours est strictement réservé aux dépôts publics.

    Ce qu’il reste à faire

    Si ton pipeline s’appuie déjà sur du caching pour accélérer les builds, pense à vérifier en même temps ta configuration cache-mode — les deux réglages touchent au même menu Actions et autant les revoir ensemble. Et si tu n’as pas encore activé les défenses anti-supply-chain sur tes workflows critiques, notre article sur le sujet reste d’actualité. Dans tous les cas, prends dix minutes cette semaine pour ouvrir les réglages Actions de tes dépôts les plus sensibles : la rétention par défaut ne correspond pas forcément à ce que ton équipe pense avoir configuré.

  • GitHub Actions cache-mode : la fin du cache poisoning silencieux

    GitHub Actions cache-mode : la fin du cache poisoning silencieux

    Le 26 juin 2026, GitHub a changé silencieusement le comportement du cache de tous les workflows déclenchés par un événement pull_request_target ou une cascade workflow_run venant d’un fork : ces jobs ne pouvaient plus écrire dans le cache, seulement le lire. Un correctif discret, mais un vrai correctif de sécurité — il bloque un scénario d’attaque documenté depuis des années : un contributeur externe pousse une pull request qui empoisonne le cache, et ton workflow push de confiance restaure ensuite cette entrée corrompue en pensant récupérer ses propres artefacts de build.

    Depuis le 10 septembre 2026, cette protection binaire (lecture seule ou rien) devient un vrai réglage. cache-mode passe en disponibilité générale sur tous les plans github.com. Voici ce que ça change pour tes pipelines, et comment configurer le bon niveau d’accès sans casser tes builds.

    Le problème du cache poisoning, en clair

    Le cache GitHub Actions n’a jamais été pensé comme un espace de stockage fiable à 100 %. N’importe quel job avec un accès en écriture peut y déposer une entrée sous une clé qu’un autre job réutilisera plus tard — c’est justement tout l’intérêt du cache : accélérer les builds en réutilisant des node_modules, des dépendances Maven ou des couches Docker déjà téléchargées.

    Le souci apparaît quand deux workflows différents partagent la même clé de cache sans partager le même niveau de confiance. Un pull_request_target tourne avec les secrets et permissions du dépôt de base, même quand il traite une PR venant d’un fork inconnu — c’est justement pour ça que ce trigger existe. Si ce job a le droit d’écrire dans le cache, un attaquant n’a besoin que d’une PR pour y glisser une dépendance modifiée. Ton workflow push suivant restaure cette entrée en toute confiance, et exécute le code injecté avec des privilèges bien supérieurs à ceux d’un simple contributeur externe.

    Ce qui a changé le 26 juin, et ce qui change le 10 septembre

    Première étape, en juin : GitHub a imposé des jetons en lecture seule pour les événements « non fiables » — pull_request_target, issue_comment, et les cascades workflow_run initiées depuis un fork, dès que le contexte pointe vers le SHA de la branche par défaut. Les événements considérés comme fiables (push, schedule, workflow_dispatch, repository_dispatch, delete, registry_package, page_build) gardaient l’accès complet. Une tentative d’écriture sur un job restreint ne fait pas échouer le job : elle génère juste un avertissement, et l’écriture est ignorée.

    Cette bascule automatique protégeait déjà l’essentiel des cas. Mais elle ne laissait aucune marge de manœuvre. Impossible, par exemple, d’autoriser un job planifié à écrire dans le cache sans le lire (pour préchauffer un cache que d’autres jobs consommeront ensuite), ou de couper complètement l’accès cache d’un job qui n’en a pas besoin. cache-mode, en GA depuis le 10 septembre, comble ce vide avec quatre valeurs :

    • read — restaure les entrées existantes, ne peut rien sauvegarder. C’est le défaut appliqué automatiquement aux événements non fiables depuis juin.
    • write — lecture et écriture, le comportement classique. Défaut pour les événements fiables comme push.
    • write-only — sauvegarde sans jamais restaurer, utile pour un job dont le seul rôle est de préchauffer le cache pour les autres.
    • none — aucun accès au cache, ni en lecture ni en écriture.

    Configurer cache-mode, au niveau workflow ou par job

    Le champ se place soit en tête de fichier (avant jobs), soit directement dans la définition d’un job (après runs-on) :

    name: Build et tests
    on: [push, pull_request_target]
    
    # Défaut pour tous les jobs du workflow
    cache-mode: read
    
    jobs:
      build:
        runs-on: ubuntu-latest
        # Ce job override le défaut du workflow
        cache-mode: write
        steps:
          - uses: actions/checkout@v6
          - uses: actions/cache@v4
            with:
              path: ~/.npm
              key: npm-${{ hashFiles('package-lock.json') }}
    

    La hiérarchie est simple à retenir : un réglage au niveau job écrase celui du workflow, et un workflow appelé (via workflow_call) ne peut jamais obtenir plus d’accès que celui accordé par l’appelant. Impossible donc pour un workflow réutilisable de s’octroyer discrètement un accès en écriture que le caller lui refuse.

    La stratégie à adopter, sans y passer trois heures

    Pas besoin de réécrire tous tes workflows dès aujourd’hui — les défauts de juin couvrent déjà le risque principal. Mais si tu veux verrouiller les choses proprement, la règle est simple : n’accorde jamais plus que ce dont un job a besoin, et pose-toi la question à chaque job qui touche à un pull_request_target.

    Un job de build classique sur push reste en write, sans y toucher. Pour un job qui tourne sur pull_request_target mais qui n’a même pas besoin de lire le cache (un simple linter, par exemple), passe-le carrément en none — ça évite qu’il consomme des jetons de cache pour rien. Et si tu as un job planifié dédié à préchauffer le cache pour la nuit suivante, write-only est fait pour ce cas précis : il alimente le cache sans jamais avoir besoin de le lire lui-même.

    Ce que je déconseille clairement : laisser write par défaut sur un workflow entier qui mélange des jobs push et des jobs déclenchés par PR externe, en comptant sur les défauts automatiques pour rattraper le coup à ta place. Ces défauts existent, mais un réglage explicite au niveau job documente ton intention — et survit à un futur changement de trigger que tu pourrais oublier de revérifier.

    FAQ

    Est-ce que cache-mode casse mes workflows existants ?

    Non. Sans le champ, chaque job garde le comportement par défaut déjà en place depuis juin : lecture seule sur événements non fiables, lecture-écriture ailleurs. cache-mode est une option à ajouter volontairement, pas un changement de comportement forcé.

    Ça marche aussi sur GitHub Enterprise Server ?

    L’annonce du 10 septembre couvre github.com sur tous les plans. Si tu es sur GHES, vérifie la version de ta plateforme avant de t’appuyer sur ce champ — les fonctionnalités Actions arrivent en général avec un décalage sur les versions on-premise.

    Une tentative d’écriture refusée fait-elle échouer le job ?

    Non. Elle génère un avertissement dans les logs et l’écriture est silencieusement ignorée. Les restaurations en lecture, elles, ne sont jamais affectées par une restriction d’écriture.

    Faut-il aussi revoir mes clés de cache existantes ?

    Pas forcément, mais c’est le bon moment pour vérifier qu’elles n’incluent pas d’éléments contrôlables par un attaquant externe (nom de branche, titre de PR) sans validation préalable. cache-mode réduit le risque d’écriture non autorisée ; il ne remplace pas une clé de cache mal construite.

    Passe à l’action

    Si tes pipelines mélangent des jobs push et des jobs déclenchés par des PR externes — dépôt open source, contributions communautaires — c’est le moment de faire l’inventaire : quels jobs ont vraiment besoin d’écrire dans le cache, et lesquels peuvent basculer en read ou none. Une demi-heure de relecture de tes fichiers YAML vaut mieux qu’un cache empoisonné découvert en production.

    Pour aller plus loin, la documentation officielle GitHub détaille la syntaxe complète des workflows, et le changelog GitHub revient sur le passage en GA de cache-mode ainsi que sur la restriction en lecture seule de juin. Si le sujet de la chaîne d’approvisionnement CI/CD t’intéresse, on avait détaillé les défenses anti-supply-chain côté GitHub Actions et npm dans un article précédent, et les leçons des attaques de mars dans celui-ci.

  • GitHub Actions et npm en 2026 : les défenses anti-supply-chain à activer maintenant

    GitHub Actions et npm en 2026 : les défenses anti-supply-chain à activer maintenant

    En mars, les attaques supply chain contre l’écosystème npm et GitHub Actions t’avaient donné des sueurs froides (on en a tiré les leçons dans cet article). Depuis, GitHub n’est pas resté les bras croisés : toute une série de protections concrètes ont été livrées tout au long de 2026, la dernière — les Workflow Execution Protections — étant passée en disponibilité générale le 17 septembre. Tu vas voir lesquelles activer en priorité sur tes pipelines, et comment.

    Pourquoi ça continue de te concerner

    Un pipeline CI/CD, c’est un accélérateur formidable… et une cible de choix. Il tourne avec des identifiants à privilèges (tokens de publication, secrets de déploiement, accès cloud), il exécute du code que tu ne maîtrises pas toujours entièrement (dépendances tierces, contributions externes), et il le fait à grande vitesse et sans supervision humaine directe. Les attaquants l’ont bien compris : plutôt que de viser une application, ils visent la chaîne qui la construit et la publie.

    La bonne nouvelle, c’est que GitHub a industrialisé ses réponses en 2026 autour de quatre axes : empêcher le compromis initial, empêcher l’exfiltration d’identifiants, ralentir la propagation d’un package compromis, et te permettre de réagir vite si ça arrive quand même. On les prend dans l’ordre.

    Empêcher le compromis initial de ton pipeline

    Un pull_request_target plus sûr par défaut

    Le déclencheur pull_request_target reste le piège numéro un : contrairement à pull_request, il exécute le workflow avec les secrets et les permissions du dépôt de base, même quand la pull request vient d’un fork. Si ton job fait un checkout du code de la fork et l’exécute (tests, build, script), tu ouvres la porte à un « pwn request » : du code non fiable qui tourne avec tes accès et peut exfiltrer tes secrets.

    GitHub a changé le comportement par défaut de actions/checkout dans ce contexte : il faut désormais un opt-out explicite après revue du risque pour que du code de fork s’exécute avec les privilèges du dépôt de base. C’est le genre de garde-fou qui t’évite l’erreur de configuration silencieuse. Le détail des bonnes pratiques est documenté dans le guide officiel « Securely using pull_request_target ».

    Workflow Execution Protections : la liste blanche des déclencheurs (GA depuis le 17 septembre 2026)

    C’est la nouveauté la plus structurante de septembre : tu peux désormais définir, au niveau entreprise, organisation ou dépôt, une liste blanche qui contrôle qui a le droit de déclencher un workflow (règles d’acteur) et quels événements peuvent le démarrer (règles d’événement), avec la possibilité de cibler des fichiers de workflow précis. Un mode « evaluate » te permet de tester la politique en conditions réelles avant de l’appliquer réellement, sans rien bloquer par erreur le premier jour.

    Détail important : sur les dépôts publics, une règle par défaut désactive désormais les événements pull_request_target, d’abord en mode évaluation — l’application effective (le blocage réel) est prévue pour le 2 novembre 2026. Si tu as des workflows publics qui en dépendent légitimement, c’est le moment de les auditer et de créer une exception explicite plutôt que de découvrir le blocage en novembre.

    Cache-mode : qui a le droit de lire ou d’écrire le cache (GA)

    Le cache d’Actions est une cible d’attaque sous-estimée : un attaquant qui parvient à écrire dans un cache partagé peut y déposer une dépendance piégée, que récupérera ensuite un job de confiance. La clé cache-mode, désormais généralement disponible, te permet d’appliquer le principe de moindre privilège au niveau du workflow ou du job :

    name: build
    on: pull_request_target
    cache-mode: read      # niveau workflow : autorise la restauration, bloque l'écriture
    
    jobs:
      build:
        runs-on: ubuntu-latest
        # cache-mode: write   # un job de confiance peut surcharger localement
        steps:
          - uses: actions/checkout@v5
          - uses: actions/cache@v4
            with:
              path: ~/.npm
              key: npm-${{ hashFiles('package-lock.json') }}
    

    Quatre valeurs possibles : read (restauration seule), write (restauration et écriture), write-only (écriture seule), none (aucun accès). Le réglage au niveau du job prévaut sur celui du workflow, y compris à travers des workflows réutilisables — un workflow appelé ne peut jamais hériter de plus de droits que celui qui l’appelle. GitHub affiche même une annotation d’avertissement si tu déclares un accès en écriture sur un événement à faible confiance comme pull_request_target. Le détail est dans le changelog GitHub officiel.

    Empêcher l’exfiltration d’identifiants

    Trusted publishing : la fin programmée des secrets à longue durée de vie

    Le trusted publishing (OIDC) permet de publier un package npm sans stocker le moindre token à durée de vie longue dans ton pipeline : GitHub échange un jeton d’identité éphémère contre une autorisation de publication au moment précis où elle a lieu. En 2026, ce mécanisme s’est étendu au-delà de GitHub Actions, avec l’ajout du support CircleCI — un signe que la filière converge vers « zéro secret long-lived » comme standard, quel que soit ton système de CI.

    Actions Network Firewall : voir ce qui sort réellement de tes runners (aperçu technique)

    Encore en aperçu technique, cette fonctionnalité journalise tout le trafic sortant de tes workflows et t’aide à repérer un comportement anormal — récupération de code malveillant, tentative d’exfiltration de credentials vers un domaine inconnu. Des restrictions d’egress réseau (bloquer les destinations non autorisées, pas seulement les journaliser) sont annoncées pour la suite. Si tu gères des pipelines sensibles, c’est une fonctionnalité à surveiller de près, y compris pendant sa phase preview.

    Ralentir la propagation d’un package compromis

    Dependabot cooldown : 3 jours de battement avant la mise à jour

    Une release npm fraîchement publiée est justement le moment où une compromission a le plus de chances de passer inaperçue. Dependabot applique désormais un délai minimum de trois jours avant d’ouvrir une pull request de mise à jour de dépendance — le temps que la communauté détecte et signale un package malveillant avant que tu ne l’intègres automatiquement. Les mises à jour de sécurité, elles, restent immédiates : ce cooldown ne s’applique qu’aux montées de version « de confort ».

    npm v12 : les scripts d’installation ne s’exécutent plus par défaut

    Beaucoup de compromissions npm passent par un postinstall malveillant qui s’exécute silencieusement dès npm install, avant même que tu aies lancé quoi que ce soit. Depuis npm v12, ces scripts d’installation sont désactivés par défaut : tu dois les réactiver explicitement si tu en as besoin, ce qui te force à une décision consciente plutôt qu’à une exécution automatique et invisible.

    Réagir vite si ça arrive quand même

    Malgré toutes ces couches de défense, prépare-toi aussi à l’incident : GitHub propose désormais une révocation d’identifiants en libre-service à l’échelle de l’entreprise (tous les identifiants utilisateurs d’un coup en cas de compromission avérée), et une API de révocation étendue qui couvre désormais les tokens OAuth et App en plus des tokens d’accès personnels. Avoir ce processus documenté et testé avant l’incident te fait gagner un temps précieux le jour où tu en as besoin.

    Check-list à appliquer cette semaine

    • Audite tes workflows utilisant pull_request_target et vérifie qu’aucun ne fait de checkout + exécution de code de fork sans contrôle.
    • Active les Workflow Execution Protections en mode évaluation sur tes dépôts sensibles pour voir l’impact avant l’application forcée du 2 novembre.
    • Passe en revue le cache-mode de tes workflows déclenchés par des événements à faible confiance.
    • Si tu publies sur npm, migre vers le trusted publishing pour éliminer les tokens de publication à longue durée de vie.
    • Documente (et teste) ta procédure de révocation de credentials en cas d’incident, avant d’en avoir besoin en urgence.

    FAQ

    Le cache-mode remplace-t-il les autres protections ?

    Non, c’est une couche parmi d’autres. Il réduit spécifiquement le risque de cache poisoning, mais ne protège pas contre l’exfiltration de secrets par un autre canal : tu as besoin des Workflow Execution Protections et d’un usage prudent de pull_request_target en complément.

    Dois-je m’inquiéter si j’utilise déjà GitHub-hosted runners standards ?

    Les runners hébergés par GitHub bénéficient déjà d’un bon niveau d’isolation par exécution, mais cela ne protège pas contre un secret exfiltré par un workflow mal configuré. Ces protections s’appliquent quel que soit le type de runner.

    Que se passe-t-il si je ne fais rien avant le 2 novembre 2026 ?

    Sur les dépôts publics, la règle par défaut désactivant pull_request_target passera du mode évaluation à l’application réelle : les workflows concernés seront bloqués s’ils ne respectent pas la politique. Autant l’anticiper maintenant en mode évaluation plutôt que de le découvrir en production.

    Ces protections concernent-elles aussi Azure Pipelines ou GitLab CI ?

    Les fonctionnalités détaillées ici sont spécifiques à GitHub Actions et à npm. D’autres plateformes CI/CD ont leurs propres mécanismes équivalents (protection des triggers, gestion des secrets, scan de dépendances) : le principe général — moindre privilège, zéro secret long-lived, délai avant adoption d’une nouvelle version — reste transposable partout.

    Pour aller plus loin

    Aucune de ces protections n’est magique prise isolément : c’est leur empilement qui fait la différence face à des attaques de plus en plus automatisées. Commence par la check-list ci-dessus sur tes dépôts les plus critiques, active le mode évaluation des Workflow Execution Protections dès maintenant, et reviens régulièrement vérifier l’avancement de l’Actions Network Firewall : c’est probablement la prochaine brique qui passera en disponibilité générale.

  • Sécurité des pipelines CI/CD en 2026 : les leçons des attaques supply chain de mars

    Sécurité des pipelines CI/CD en 2026 : les leçons des attaques supply chain de mars

    En mars 2026, quatre outils utilisés quotidiennement dans des pipelines CI/CD partout dans le monde — Trivy, Checkmarx KICS, LiteLLM et une dépendance de axios — se sont retrouvés compromis en l’espace de deux semaines. Pas des outils obscurs : des scanners de sécurité et des librairies que des dizaines de milliers d’équipes exécutent en confiance, sans y penser, à chaque build. Si ta pipeline CI/CD ressemble à la plupart — des actions tierces épinglées sur un tag, des secrets stockés en clair, aucune vérification de provenance sur ce qui sort en production — ces incidents te concernent directement. On fait le point sur ce qui s’est passé, les schémas d’attaque qui reviennent, et surtout les défenses concrètes à mettre en place sur Azure DevOps ou GitHub Actions.

    Ce qui s’est passé en mars 2026

    Entre le 19 et le 31 mars 2026, une série de compromissions a touché des composants au cœur de nombreuses pipelines CI/CD, comme l’a documenté l’analyse post-mortem publiée par GitLab :

    • Trivy, le scanner de vulnérabilités utilisé dans d’innombrables jobs de scan de conteneurs, a été compromis par un malware volant les secrets présents dans l’environnement d’exécution.
    • Checkmarx KICS, un scanner IaC largement utilisé pour auditer du Terraform et du Bicep, a subi une injection similaire de vol de credentials.
    • LiteLLM, une passerelle vers des API de LLM de plus en plus intégrée dans les workflows d’automatisation, a livré des versions PyPI trojanisées contenant des backdoors.
    • Une dépendance transitive de axios (le module plain-crypto-js) s’est révélée malveillante, touchant potentiellement tout projet JavaScript qui l’incluait sans le savoir.

    Un cinquième incident, distinct mais révélateur du même laxisme ambiant, a montré des source maps npm non filtrées exposant du code source en production.

    Trois schémas d’attaque qui reviennent

    Ce n’est pas un hasard si ces incidents se ressemblent. Ils exploitent trois failles structurelles qu’on retrouve dans la grande majorité des pipelines :

    La confiance implicite envers les outils et actions

    Une action GitHub référencée par un tag mutable (@v3 plutôt qu’un digest de commit), une image Docker tirée par son tag latest, un scanner installé sans vérification de checksum : autant de points où tu fais confiance à ce qui a été publié la dernière fois que tu as regardé, pas à ce qui tourne réellement aujourd’hui.

    Les erreurs de configuration

    Artefacts de debug oubliés dans un build de production, logs verbeux qui exposent des tokens, permissions de pipeline trop larges par défaut — ces erreurs classiques transforment une simple compromission d’outil en fuite de données complète.

    La propagation par dépendances transitives

    Tu audites peut-être tes dépendances directes. Mais une seule version compromise, plusieurs niveaux en dessous dans l’arbre de dépendances, se propage silencieusement à tout ce qui en dépend — comme l’a montré l’incident axios.

    Les défenses concrètes à mettre en place

    Passer à une authentification sans secret

    La première chose qu’un attaquant cherche dans une pipeline compromise, ce sont des secrets à long terme : tokens Azure, clés d’API, mots de passe de service principal. La parade recommandée par Microsoft dans le Cloud Adoption Framework est de basculer sur l’authentification par fédération d’identité (OpenID Connect) pour tes connexions de service Azure DevOps comme pour tes workflows GitHub Actions — plus aucun secret client à stocker, donc plus rien à voler. On a détaillé la mise en œuvre côté Azure DevOps dans notre article sur la fédération d’identité pour les service connections.

    Épingler aux digests, jamais aux tags

    Un tag comme actions/checkout@v4 peut techniquement pointer vers un commit différent demain si le mainteneur (ou un attaquant ayant compromis son compte) le déplace. Épingler sur le digest SHA immuable (actions/checkout@a1b2c3d...) garantit que tu exécutes exactement le code que tu as audité, pas une version substituée après coup. Le même principe s’applique à tes images de base Docker : préfère un digest à un tag latest ou même à un tag de version.

    Générer un SBOM et scanner tes dépendances en continu

    Un inventaire à jour de tout ce qui compose ton build (SBOM — Software Bill of Materials) est ce qui te permet de répondre en quelques minutes, et non en plusieurs jours, à la question « est-ce qu’on utilise le composant compromis ?» le jour où un incident comme celui de mars 2026 est annoncé. Couplé à une analyse de composition logicielle (SCA) et à des outils comme Dependabot pour la mise à jour automatique des dépendances vulnérables, c’est la base d’une hygiène supply chain sérieuse.

    Vérifier la provenance de ce que tu déploies

    Les attestations de provenance (SLSA, Supply-chain Levels for Software Artifacts) permettent de prouver cryptographiquement qu’un artefact a bien été construit par ta pipeline, à partir du code source attendu, et qu’il n’a pas été substitué entre le build et le déploiement. GitHub propose nativement les Artifact Attestations, qui permettent d’atteindre le niveau SLSA 3 sans infrastructure supplémentaire à opérer toi-même. Encore émergent début 2026 mais à surveiller de près : les fonctionnalités de type « Dependency Firewall » qui bloquent automatiquement l’installation de versions connues comme compromises, avant même l’exécution du job.

    Isoler tes runners self-hébergés

    Un runner self-hosted partagé entre plusieurs projets, avec un accès réseau large et une identité trop permissive, est une cible de choix : une seule pipeline compromise donne potentiellement accès à tout ce que ce runner peut atteindre. Isole tes runners par niveau de confiance (production vs. développement), limite leurs permissions réseau sortantes, et évite de leur attacher des identités managées avec des droits qui dépassent largement ce dont un job donné a besoin.

    Une checklist pour ta prochaine revue de pipeline

    Avant ta prochaine passe de sécurisation, vérifie que tu coches ces points, qu’on ait affaire à GitHub Actions, Azure Pipelines ou GitLab CI :

    • Aucun secret à longue durée de vie dans les pipelines : authentification via OIDC / workload identity federation partout où c’est possible
    • Actions et images tierces épinglées par digest, pas par tag
    • SBOM généré à chaque build et scan de dépendances actif (Dependabot ou équivalent)
    • Attestations de provenance activées sur les artefacts qui partent en production
    • Approbations obligatoires sur les modifications de configuration CI/CD elle-même, pas seulement sur les déploiements
    • Runners self-hébergés isolés par niveau de confiance, avec des permissions réseau et des identités minimales

    FAQ

    Le passage aux digests casse-t-il les mises à jour automatiques de dépendances ?

    Non, à condition d’utiliser un outil comme Dependabot ou Renovate qui sait résoudre et mettre à jour les digests automatiquement via des pull requests — tu gardes la traçabilité et la revue humaine, sans revenir à un tag mutable.

    Faut-il migrer toutes les pipelines d’un coup ?

    Non, commence par les pipelines qui déploient en production et celles qui manipulent des secrets sensibles. L’authentification sans secret et l’épinglage par digest sont les deux mesures avec le meilleur ratio effort/impact pour démarrer.

    Les attestations SLSA sont-elles seulement pour GitHub Actions ?

    Le concept est indépendant de la plateforme : GitHub propose une implémentation native, mais des équivalents existent ou émergent pour Azure Pipelines et GitLab CI via des outils tiers comme Sigstore/cosign.

    Passe à l’action

    Les incidents de mars 2026 n’ont épargné personne parce qu’ils ciblaient l’angle mort classique : la confiance aveugle envers ce qui tourne « habituellement » dans une pipeline. Prends une heure cette semaine pour auditer tes connexions de service, vérifie si tes actions critiques sont épinglées par tag ou par digest, et active un scan de dépendances si ce n’est pas déjà fait. Ce sont trois changements simples qui réduisent drastiquement ta surface d’attaque, sans ralentir tes déploiements.

  • GitHub Actions en septembre 2026 : les nouveautés sécurité et la feuille de route à connaître

    GitHub Actions en septembre 2026 : les nouveautés sécurité et la feuille de route à connaître

    Si tes pipelines GitHub Actions tournent depuis un moment sans que tu aies retouché aux permissions ou à l’épinglage des actions tierces, cet article est pour toi. GitHub a publié début septembre 2026 trois nouveautés qui touchent directement la sécurité et la fiabilité de tes workflows, et elles s’inscrivent dans une feuille de route 2026 bien plus large sur le sujet. Tu vas voir ce qui change concrètement, comment en profiter dès maintenant, et ce qui arrive ensuite pour que tu puisses anticiper plutôt que subir.

    Ce qui vient de sortir : les mises à jour de début septembre 2026

    Le changelog officiel du 3 septembre 2026 apporte trois changements concrets.

    1. Une API pour anticiper la dépréciation des runners

    Nouvel endpoint REST : GET /actions/runners/deprecations/{version}, disponible au niveau repository, organisation ou entreprise. Il te renvoie runner_version, runtime_deprecates_at et registration_deprecates_at — de quoi programmer tes montées de version de runners self-hosted au lieu de découvrir la dépréciation le jour où un job casse en production.

    curl -H "Authorization: Bearer $GH_TOKEN" \
      -H "Accept: application/vnd.github+json" \
      https://api.github.com/repos/ORG/REPO/actions/runners/deprecations/2.319.1

    2. Une permission dédiée aux alertes Dependabot

    Le GITHUB_TOKEN gagne une permission vulnerability-alerts (valeurs read ou none), qui donne un accès en lecture seule aux alertes Dependabot depuis un workflow. Ça t’évite de devoir accorder des scopes beaucoup plus larges juste pour qu’un job lise l’état des vulnérabilités connues :

    permissions:
      vulnerability-alerts: read
      contents: read

    C’est exactement le genre de granularité que recommande la documentation officielle sur l’usage sécurisé de GitHub Actions : donner à chaque job le minimum nécessaire, jamais plus.

    3. Quatre nouvelles propriétés de contexte pour les workflows réutilisables

    Si tu factorises tes pipelines avec des reusable workflows, le contexte job expose désormais job.workflow_ref, job.workflow_sha, job.workflow_repository et job.workflow_file_path. Ça permet à un workflow réutilisable de savoir précisément d’où il est appelé et sur quelle version — utile pour du logging, de l’audit, ou pour appliquer des règles différentes selon l’appelant. Seule limite à noter : ces propriétés ne sont pas disponibles sur GitHub Enterprise Server.

    La feuille de route sécurité 2026 : ce qui arrive ensuite

    Ces trois nouveautés s’inscrivent dans une feuille de route sécurité plus large que GitHub a partagée avec la communauté. Voici les chantiers à surveiller, parce qu’ils vont probablement changer tes habitudes de configuration :

    • Verrouillage des dépendances au niveau workflow : à terme, les actions tierces devront être épinglées à un SHA de commit précis pour que le workflow s’exécute — la meilleure protection connue contre une action compromise qui pousserait une mise à jour malveillante sur son tag.
    • Protections sur le déclenchement des workflows : donner aux administrateurs un contrôle plus fin sur quels acteurs et quels événements peuvent déclencher un workflow, en particulier pour les opérations sensibles (déploiement, publication de packages).
    • Secrets mieux scopés : limiter l’accès aux secrets par workflow, par job, voire par step, plutôt que de les exposer à l’ensemble d’un run.
    • Flux d’audit immuable (« actions data stream ») : une piste d’audit séparée des logs de run classiques, pensée pour rester exploitable même si un run est compromis et ses logs supprimés, avec une intégration envisagée vers des outils SIEM.
    • Pare-feu de sortie natif : blocage par défaut du trafic sortant des runners hébergés par GitHub, avec liste d’autorisation — d’abord sur les runners managés, le support des runners self-hosted étant encore à l’étude.

    Rien de tout ça n’est encore généralisé au moment où j’écris ces lignes, mais la direction est claire : GitHub muscle sérieusement la sécurité par défaut de ses pipelines, dans la continuité des attaques de chaîne d’approvisionnement qui ont touché plusieurs actions populaires ces dernières années.

    Ce que tu peux faire dès maintenant

    Épingler tes actions tierces sans attendre l’obligation

    Plutôt que d’attendre que ça devienne obligatoire, remplace dès aujourd’hui tes références de tags (uses: actions/checkout@v4) par des SHA de commit complets :

    steps:
      - uses: actions/checkout@8edcb1bdb4e267140fa742c62e395cd74f332d84 # v4.2.2
    

    Ça demande un peu plus de maintenance (Dependabot peut s’en charger automatiquement), mais ça neutralise le scénario où un tag existant est réécrit pour pointer vers du code malveillant.

    Auditer tes permissions existantes

    Beaucoup de workflows historiques tournent encore avec des permissions par défaut trop larges. Un audit rapide consiste à passer en revue chaque fichier .github/workflows/*.yml et à vérifier qu’un bloc permissions explicite est défini au niveau du workflow ou du job, plutôt que de laisser GitHub appliquer ses valeurs par défaut.

    Ne pas négliger les runners self-hosted

    Si une partie de tes workflows tourne sur des runners self-hosted plutôt que sur l’infrastructure managée par GitHub, garde en tête que plusieurs des protections à venir (pare-feu de sortie notamment) cibleront d’abord les runners hébergés par GitHub. Sur du self-hosted, la responsabilité du durcissement réseau et système reste largement la tienne — un sujet sur lequel Azure DevOps propose une approche comparable avec ses Managed DevOps Pools, si tu veux comparer les deux écosystèmes.

    FAQ

    Faut-il déjà épingler toutes ses actions par SHA ?

    Ce n’est pas encore obligatoire, mais c’est déjà une bonne pratique recommandée par GitHub, en particulier pour les actions tierces peu maintenues ou à fort accès (secrets, déploiement). Pour les actions officielles GitHub, le risque est plus faible mais le principe reste valable.

    La permission vulnerability-alerts remplace-t-elle un scope Dependabot plus large ?

    Oui, dans les cas où un workflow n’a besoin que de lire l’état des alertes Dependabot. Avant cette permission dédiée, il fallait souvent accorder des droits plus étendus sur le repository pour arriver au même résultat.

    Le pare-feu de sortie va-t-il casser mes workflows actuels ?

    Une fois généralisé, oui potentiellement, si tes jobs contactent des services externes non listés dans l’allowlist. C’est justement pour ça qu’il vaut mieux commencer dès maintenant à documenter les destinations réseau utilisées par tes workflows, plutôt que de le découvrir en heurtant un blocage.

    En résumé

    Les nouveautés de septembre 2026 sont modestes prises isolément, mais elles annoncent une évolution de fond : GitHub Actions va progressivement imposer une hygiène de sécurité qui, aujourd’hui encore, dépend surtout de la discipline de chaque équipe. Autant prendre les devants — épingler tes actions, resserrer tes permissions, documenter tes flux réseau — plutôt que de découvrir ces contraintes le jour où elles deviennent obligatoires.