Un Mac Runner partagé commence à lire des fichiers d’un autre dépôt, ou une tâche de test laisse un processus actif après son achèvement.
La solution la plus rapide est de refuser tout code public ou non approuvé, puis de n’autoriser un Runner privé qu’avec un groupe isolé, un nœud de signature séparé et une procédure de nettoyage vérifiable.
Cette analyse de la sécurité d’un Mac Runner auto-hébergé GitHub Actions s’adresse aux équipes qui exécutent des builds Xcode et des tests Simulator. Elle concerne aussi les ingénieurs DevOps qui administrent les groupes de runners, les règles réseau et les comptes macOS. Les responsables de la signature Apple et des mises en production y trouveront les critères de refus.
Qualification de confiance
Le premier contrôle ne porte pas sur l’état « Online ». Il porte sur le code que le nœud peut exécuter et sur les personnes qui peuvent modifier le workflow, déclencher une tâche ou approuver un environnement.
GitHub indique que les runners auto-hébergés ne bénéficient pas de la même garantie d’environnement temporaire et propre qu’un Runner géré. La documentation officielle avertit également du risque de compromission persistante lorsqu’un workflow exécute du code non fiable sur un hôte durable : consignes de sécurité pour GitHub Actions.
Pour un dépôt public, la décision par défaut est donc « interdit » si le Mac contient un certificat, un accès privé ou une session de développement. Une demande de modification issue d’une personne extérieure peut modifier les étapes exécutées, lire des fichiers accessibles au compte du Runner ou installer une persistance.
Un dépôt privé n’est pas automatiquement fiable. Vérifiez qui peut inviter des collaborateurs, modifier les workflows, créer des branches, approuver les environnements et lancer manuellement une tâche. Une compromission d’un compte autorisé peut produire le même effet qu’un dépôt public malveillant.
Liste de validation de la confiance
- [ ] Le niveau de confiance du dépôt est documenté : public, privé contrôlé ou non approuvé.
- [ ] Les auteurs autorisés à modifier les workflows sont connus.
- [ ] Les déclencheurs
pull_request,workflow_dispatchet les événements de branche sont revus. - [ ] La personne qui approuve une publication est distincte de celle qui modifie le workflow.
- [ ] Le Runner utilisé pour les essais ne contient aucun secret de production.
- [ ] Une tâche provenant d’un dépôt interdit est rejetée et cette preuve est conservée.
| Situation observée | Décision pour le Mac Runner | Repli acceptable |
|---|---|---|
| Dépôt public ou code externe non examiné | Refuser l’accès au nœud durable | Nœud jetable sans secret ou exécution gérée |
| Dépôt privé, mais workflows modifiables par de nombreux comptes | Isoler pour un build sans signature | Revue manuelle avant tout accès sensible |
| Dépôt contrôlé, déclencheurs limités et nettoyage prouvé | Autoriser le build selon les privilèges requis | Nœud de publication séparé pour la signature |
Groupes et routage
Le deuxième indicateur est la route réellement suivie par chaque tâche. Un Runner enregistré au niveau du dépôt n’a pas le même périmètre qu’un Runner associé à une organisation ou à une entreprise. Une configuration trop large peut exposer un Mac à des dépôts qui n’étaient pas prévus dans le plan initial.
Les Runner Groups permettent de limiter les dépôts autorisés. La documentation GitHub décrit leur portée et les règles d’accès à contrôler : fonctionnement des Runner Groups.
Nous vérifions quatre objets ensemble :
- le niveau d’enregistrement du Runner ;
- la liste blanche des dépôts pouvant utiliser le groupe ;
- les étiquettes associées au nœud ;
- les conditions du workflow qui choisissent l’exécuteur.
Une étiquette telle que macos-arm décrit une capacité. Elle ne doit pas devenir la seule barrière de sécurité. Le routage doit rester refusé lorsque le dépôt n’appartient pas à la liste autorisée, même si le workflow connaît l’étiquette.
La sélection d’un Runner dans un workflow doit être comparée à la politique du groupe, et non analysée isolément. La documentation GitHub sur le choix de l’exécuteur explique cette relation entre labels, groupes et tâche : routage d’un job vers un Runner.
Preuves d’acceptation
- [ ] Le groupe auquel appartient le Runner est identifié.
- [ ] Les dépôts autorisés sont listés explicitement.
- [ ] Un dépôt autorisé atteint le nœud prévu.
- [ ] Un dépôt non autorisé est refusé.
- [ ] Une étiquette inconnue ou mal utilisée ne contourne pas le groupe.
- [ ] Le résultat d’acceptation et le résultat de refus sont conservés dans le dossier d’exploitation.
Si le groupe est partagé entre plusieurs équipes, nous séparons au minimum les builds ordinaires et les tâches capables de produire un artefact de distribution. Pour un Mac utilisé à la fois par une équipe audio, une équipe vidéo et une chaîne Xcode, cette séparation évite qu’un projet de montage ou de design conserve accidentellement des fichiers dans l’espace d’un build mobile.
Comptes, jetons et signature
Le troisième indicateur concerne la valeur des secrets exposés. Un GITHUB_TOKEN limité à la lecture n’a pas le même impact qu’une clé de déploiement, qu’un certificat Apple ou qu’une identité autorisant une publication.
Il faut distinguer les couches suivantes :
- le jeton de lecture du dépôt ;
- les clés permettant de publier un artefact ;
- les certificats et clés privées Apple ;
- les droits de publication vers une distribution ou un environnement de production.
Le GITHUB_TOKEN doit recevoir uniquement les permissions nécessaires au job. Les droits d’écriture ne doivent pas être hérités par défaut lorsqu’un build ne fait que compiler ou exécuter des tests.
L’approbation d’un environnement apporte une décision supplémentaire avant une étape sensible. Elle ne transforme toutefois pas un hôte déjà contrôlé par du code non fiable en hôte sain. GitHub décrit les règles d’environnements et les approbations dans sa documentation sur les déploiements : environnements et approbations de workflow.
Le macOS Keychain doit être examiné au niveau du compte qui exécute le Runner. Il faut savoir quelle session peut déverrouiller l’élément, quelles commandes peuvent l’utiliser et si une tâche de build peut accéder à d’autres identités du même trousseau. Apple décrit la structure et le comportement des certificats de signature dans sa note technique : limites et fonctionnement des certificats de signature Apple.
| Actif | Nœud de build général | Nœud de signature et publication |
|---|---|---|
| Source et dépendances | Autorisé après contrôle du dépôt | Autorisé seulement si nécessaire |
| Tests Xcode et Simulator | Autorisés | Autorisés |
| Clé privée Apple | Interdite | Autorisée sous compte dédié |
| Accès au Keychain de publication | Interdit | Limité au job concerné |
| Approbation de production | Inaccessible | Requise avant la dernière étape |
| Dépôt non approuvé | Refusé | Toujours refusé |
Nous retenons un nœud de signature séparé lorsque le workflow traite une identité Apple, une archive destinée à la distribution ou un accès persistant au Keychain. Un simple secret masqué dans les journaux ne suffit pas : le processus du job peut encore lire des fichiers, appeler des outils locaux ou modifier la configuration de l’utilisateur.
Résidus et confiance après tâche
Un Runner de longue durée conserve davantage que le répertoire du dépôt. Nous inspectons DerivedData, les archives Xcode, les caches de dépendances, les journaux, les fichiers temporaires et les variables enregistrées par des scripts. Les processus enfants sont tout aussi importants : un agent lancé en arrière-plan peut rester actif après le retour au statut « Terminé ».
Un nettoyage acceptable comprend au moins les opérations suivantes :
- [ ] supprimer la copie du dépôt et les fichiers générés sensibles ;
- [ ] rechercher les archives, journaux et fichiers temporaires liés au job ;
- [ ] arrêter les processus issus de la tâche ;
- [ ] vérifier les agents de démarrage et les tâches planifiées ;
- [ ] contrôler les préférences utilisateur et les modifications de configuration ;
- [ ] rechercher les traces de certificats, jetons et mots de passe ;
- [ ] vérifier le Keychain avec le compte d’exécution concerné ;
- [ ] redémarrer le nœud lorsque la politique l’impose, puis refaire un contrôle.
Attention : supprimer le dossier de travail ne prouve pas que le Mac est redevenu fiable. Un processus, une tâche planifiée, une modification du shell ou une donnée placée dans le Keychain peut survivre à cette suppression.
Pour un Mac impossible à reconstruire automatiquement, nous définissons une condition d’arrêt stricte. Une anomalie de processus, une différence inexpliquée dans la configuration ou une trace de secret hors de son emplacement attendu suffit à suspendre les tâches de signature et de publication. Le nœud passe alors en revue manuelle ou en remplacement.
La documentation GitHub sur les runners compromis rappelle précisément pourquoi la persistance doit être traitée comme un risque propre à l’hôte, et non comme un simple échec de tâche : réponse à un Runner compromis.
Réseau et privilèges
Un Mac compromis ne doit pas pouvoir atteindre automatiquement tout le réseau de l’entreprise. Nous établissons la liste des cibles nécessaires au build : registre de dépendances, dépôt source, service de test, serveur d’artefacts et éventuellement service de signature.
Chaque accès est classé en « autorisé », « non nécessaire » ou « interdit ». Le résultat attendu n’est pas seulement une liste de règles pare-feu. Il faut montrer qu’une destination nécessaire fonctionne et qu’une destination sensible sans justification est effectivement bloquée.
Les contrôles portent sur :
- le réseau interne accessible depuis le compte du Runner ;
- les hôtes de gestion et les interfaces d’administration ;
- les registres de paquets et leurs identifiants ;
- les services de signature ou de publication ;
- l’accès sortant vers Internet ;
- les privilèges
root, les extensions système et les autorisations de disque.
Un build Xcode ou un test Simulator n’a pas automatiquement besoin de droits d’administration permanents. Une étape qui exige root doit être isolée dans un job explicite, avec une justification, une approbation et une preuve de son résultat. Si la tâche ordinaire nécessite un accès illimité au disque, nous revenons à un nœud non sensible ou à une architecture reconstruite après usage.
Validation et reprise
La dernière étape est une répétition contrôlée du risque réel. Nous ne validons pas un nœud parce qu’il est visible dans l’interface GitHub. Nous exécutons un build à faible privilège, une opération de signature contrôlée, une simulation de résidu malveillant et un redémarrage.
Le plan de validation doit démontrer :
- qu’un workflow autorisé atteint le bon Runner ;
- qu’un workflow interdit est refusé ;
- qu’un job sans permission de publication ne peut pas l’obtenir par héritage ;
- qu’un résidu laissé volontairement est détecté ;
- qu’un redémarrage ne réactive pas un processus inattendu ;
- que les journaux permettent de reconstituer l’action et l’identité concernées ;
- que les secrets peuvent être révoqués et remplacés ;
- qu’un Mac de secours peut reprendre le service sans copier aveuglément l’état du nœud suspect.
GitHub confirme l’existence de mécanismes tels que les groupes de runners, les politiques de dépôt et les runners à durée de vie limitée. Ils améliorent le routage et le cycle de vie, mais ne doivent pas être confondus avec un nettoyage complet du système hôte. La documentation générale des runners auto-hébergés décrit ces limites de responsabilité : documentation GitHub des runners auto-hébergés.
Décision d’exploitation
- Si le dépôt est contrôlé, le groupe est limité, les permissions sont minimales et le nettoyage est prouvé, alors autorisez les builds sans secret de publication.
- Si le workflow manipule une identité Apple ou un artefact de distribution, alors utilisez un nœud de signature distinct avec approbation d’environnement.
- Si le Mac partagé ne peut pas être reconstruit, alors limitez-le aux tâches à faible privilège et excluez toute signature.
- Si une trace persistante ou un accès réseau inattendu est détecté, alors arrêtez immédiatement la distribution et remplacez ou réinstallez le nœud.
- Si la séparation ne peut pas être démontrée par une tâche acceptée et une tâche refusée, alors la configuration n’est pas prête pour la production.
- Si l’équipe ne peut pas assurer la rotation des secrets et la reprise sur un autre Mac, alors utilisez un environnement d’exécution géré ou réduisez le périmètre du Runner.
Pour préparer un essai sans engager la chaîne de publication, nous pouvons commencer par un environnement Mac distant pour les tests CI. Une équipe qui préfère administrer un hôte dédié peut aussi examiner une configuration Mac mini pour les tâches de commande à distance, mais elle doit appliquer la même séparation des comptes, des secrets et des réseaux.
Questions fréquentes
Un dépôt public peut-il utiliser un Runner auto-hébergé ?
Un Runner auto-hébergé peut techniquement être associé à un dépôt public, mais nous refusons cette combinaison dès que le Mac contient des secrets, un accès interne ou un état durable. Le code public et les demandes de modification externes doivent être considérés comme non fiables jusqu’à leur revue. Pour un test, choisissez un nœud sans secret, limité au réseau nécessaire et facile à reconstruire.
Comment séparer plusieurs dépôts sur un Mac partagé ?
Commencez par un Runner Group avec une liste blanche de dépôts, puis contrôlez les événements qui peuvent déclencher un workflow. Ajoutez des comptes macOS distincts si les dépôts ont des niveaux de confiance différents. Les labels servent au routage fonctionnel, pas à l’autorisation principale. Enfin, prouvez la séparation avec un dépôt autorisé et un dépôt explicitement refusé.
Quel Runner doit contenir les certificats Xcode ?
Les certificats et clés privées Apple doivent rester sur un Runner de publication distinct du nœud qui accepte les builds ordinaires ou les demandes de modification non approuvées. Le compte d’exécution doit être dédié, le Keychain limité et l’étape soumise à une approbation. Aucun contrôle d’environnement ne compense un hôte déjà maîtrisé par le code du job.
Quelles données nettoyer après une tâche ?
Nettoyez le dépôt, les fichiers temporaires, les archives, les journaux sensibles et les données DerivedData lorsque leur conservation n’est pas justifiée. Inspectez aussi les processus, agents de démarrage, préférences, tâches planifiées, accès au Keychain et modifications réseau. Un contrôle limité au répertoire de travail laisse passer des résidus capables de survivre au job suivant.
Quand retirer un Runner durable du service ?
Retirez-le dès qu’un processus, une tâche planifiée, un secret ou une modification de configuration ne correspond pas à la référence approuvée. Si l’hôte ne peut pas être reconstruit ou examiné avec suffisamment de certitude, suspendez la signature et la publication. Conservez les preuves, faites tourner les secrets concernés et remplacez le nœud avant sa réintégration.
Choisir le bon niveau d’isolation
Un Mac Runner auto-hébergé peut convenir aux builds Xcode et aux tests Simulator, mais sa sécurité dépend du contrôle de l’hôte, pas de son seul statut en ligne. La solution actuelle devient fragile lorsqu’un même Mac conserve simultanément le code de plusieurs dépôts, les certificats Apple et une route vers le réseau interne : le nettoyage est difficile à prouver, la reconstruction peut être lente et une erreur de routage élargit immédiatement l’impact.
La location d’un Mac distant MESHLAUNCH peut alors servir de terrain d’essai séparé pour un dépôt non productif, avec une validation centrée sur le compte d’exécution, le redémarrage et la capacité de remise en état. Elle n’est pas une dispense de contrôle : avant d’y déplacer une signature ou une publication, nous devons conserver les preuves d’isolement exigées par le même runbook. Pour une charge stable et permanente nécessitant des interfaces physiques ou une maîtrise totale du matériel, l’achat et l’administration d’un Mac dédié restent parfois plus adaptés.