Aller au contenu
CI/CD & Automatisation medium

Durcir vos runners GitHub Actions avec Harden-Runner

9 min de lecture

Un runner GitHub Actions peut, par défaut, contacter n'importe quelle adresse sur Internet. Si une dépendance ou une action tierce est compromise, elle exfiltre vos secrets sans rencontrer le moindre obstacle. Harden-Runner est un agent de sécurité qui fonctionne comme un EDR pour vos runners : il surveille le trafic réseau, l'intégrité des fichiers et les processus, puis vous laisse bloquer ce qui n'est pas explicitement autorisé. Ce guide vous montre comment l'auditer, restreindre son egress à une allowlist, désactiver sudo et repérer une compromission. Prérequis : un dépôt avec des workflows et la maîtrise de l'épinglage des actions par SHA. Exemples testés avec Harden-Runner v2.20.0.

Harden-Runner est une action open source éditée par StepSecurity qui installe un agent de sécurité sur le runner, au tout début du job. Là où les scanners comme zizmor ou poutine analysent vos fichiers de workflow avant exécution, Harden-Runner agit pendant le build. Il observe en temps réel trois choses :

  • le trafic réseau sortant (egress), chaque connexion étant rattachée au step qui l'émet ;
  • l'intégrité des fichiers modifiés durant le job ;
  • les processus lancés sur le runner.

C'est cette surveillance à l'exécution qui a permis de détecter des attaques supply chain réelles, comme la compromission de l'action tj-actions/changed-files en 2025, où un runner exfiltrait des secrets vers une adresse inattendue.

Prenons un workflow d'intégration continue banal. Il récupère le code, installe des dépendances, lance des tests. Rien de suspect en apparence, mais rien ne limite le réseau : si l'une des dépendances installées contient une charge malveillante, elle peut expédier GITHUB_TOKEN ou vos secrets vers le serveur de l'attaquant, et le build réussira comme si de rien n'était.

On ne bloque jamais à l'aveugle. La bonne démarche commence par le mode audit, qui observe sans rien couper et dresse la liste des endpoints réellement contactés par votre workflow. Harden-Runner doit être le tout premier step du job, avant le checkout, pour intercepter l'ensemble du trafic. Épinglez-le par SHA, comme toute action tierce :

name: CI durci
on:
push:
branches: [main]
permissions: {}
jobs:
build:
name: Build et test
runs-on: ubuntu-24.04
timeout-minutes: 10
permissions:
contents: read
steps:
- name: Durcir le runner
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
- name: Récupérer le code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Construire
run: make build

À l'issue du run, Harden-Runner publie une synthèse des connexions dans les logs du job et sur le tableau de bord StepSecurity. Vous y voyez chaque destination jointe, associée au step qui l'a émise : le point de départ pour établir votre allowlist.

Le résultat de l'audit est consultable de deux façons. Dans l'onglet du job, Harden-Runner ajoute un récapitulatif listant les domaines contactés. Sur le tableau de bord app.stepsecurity.io, une vue plus riche corrèle connexions, fichiers et processus, et vous propose directement les recommandations de durcissement, par exemple désactiver sudo si le job ne s'en sert pas.

L'objectif de cette lecture est simple : distinguer les endpoints légitimes (le registre de paquets, l'API GitHub, votre miroir interne) des connexions que vous ne vous expliquez pas. Les premiers formeront l'allowlist, les secondes méritent une enquête.

Une fois la liste des destinations légitimes établie, passez egress-policy à block et déclarez-les dans allowed-endpoints, au format hôte:port, une par ligne. Toute connexion vers une destination absente de la liste est alors coupée, aux couches DNS et réseau.

- name: Durcir le runner
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: block
allowed-endpoints: >
github.com:443
api.github.com:443
objects.githubusercontent.com:443

Désormais, la charge malveillante du scénario précédent se heurte à un mur : sa tentative de connexion vers le serveur de l'attaquant est bloquée, et l'événement apparaît en rouge dans les insights. Le filtrage egress transforme une exfiltration silencieuse en alerte visible.

Le filtrage egress se complète de deux réglages utiles. Les runners GitHub-hosted accordent un sudo sans mot de passe : un outil de build compromis peut donc installer ce qu'il veut. Si votre job n'en a pas besoin, coupez cet accès. L'input historique disable-sudo est en cours de dépréciation au profit de disable-sudo-and-containers, qui retire aussi l'accès aux conteneurs :

- name: Durcir le runner
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: block
disable-sudo-and-containers: true
allowed-endpoints: >
github.com:443
api.github.com:443

L'input disable-telemetry empêche l'agent d'envoyer ses données à l'API StepSecurity, utile si votre politique interdit toute télémétrie sortante. Pour les organisations, une policy centralisée (inputs policy, api-key, use-policy-store) permet de définir l'allowlist une seule fois et de l'appliquer à tous les dépôts, plutôt que de la répéter dans chaque workflow.

Harden-Runner est un excellent garde-fou, à condition de connaître ses bornes.

PiègeRéalitéBon réflexe
Placer l'action après checkoutLe trafic antérieur échappe à la surveillanceEn faire le premier step du job
L'épingler par tag @v2Une action tierce mobile peut être détournéeÉpingler par SHA (règle GHA-01)
Croire le blocage infaillibleUn contournement egress via DNS-over-HTTPS a existé sur l'offre gratuiteTenir l'agent à jour, combiner à d'autres contrôles
Compter sur disable-sudo seulLa CVE-2025-32955 permettait de le contournerVersion ≥ 2.12.0 et disable-sudo-and-containers
L'attendre partoutL'agent cible les runners UbuntuPrévoir une autre approche sur macOS/Windows

Retenez surtout que Harden-Runner s'inscrit dans une défense en profondeur. Il ne remplace ni l'épinglage par SHA, ni les permissions minimales, ni l'analyse statique des workflows : il ajoute la couche d'exécution qui manquait, celle qui voit ce qui se passe pendant le build.

Harden-Runner se décline en deux offres. La version Community, gratuite et suffisante pour l'essentiel, couvre exactement ce que montre ce guide : audit et blocage de l'egress, allowlist d'endpoints, désactivation de sudo, et le récapitulatif des connexions dans le job. C'est le socle à déployer sur tous vos dépôts.

L'offre Enterprise ajoute une gestion centralisée (le policy store, pour définir une politique unique appliquée à toute l'organisation), une surveillance plus fine des processus, la corrélation historique des exécutions et des alertes sur comportements anormaux. Elle vise les équipes qui doivent prouver et piloter la conformité de nombreux pipelines. Commencez par la version Community : elle bloque déjà la classe d'attaques la plus courante.

  • Harden-Runner surveille un runner GitHub Actions à l'exécution : trafic egress, intégrité des fichiers, processus.
  • Commencez toujours en egress-policy: audit pour découvrir les endpoints réellement utilisés.
  • Passez ensuite en block avec allowed-endpoints (hôte:port) pour couper toute exfiltration.
  • Faites-en le premier step du job et épinglez-le par SHA, sinon la protection est incomplète.
  • Coupez sudo avec disable-sudo-and-containers (qui remplace disable-sudo) quand le job n'en a pas besoin.
  • C'est une couche de défense en profondeur, pas un substitut à l'épinglage, aux permissions minimales et à l'analyse statique.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn