Une tâche de build peut fonctionner parfaitement dans un terminal interactif, puis afficher « impossible d’ouvrir » ou « opération non autorisée » sur un runner sans surveillance, voire s’arrêter immédiatement après son lancement. Le premier réflexe consiste souvent à exécuter chmod +x. Pourtant, lorsque le fichier possède déjà les droits d’exécution, le blocage vient généralement de Gatekeeper, de la vérification de la signature du code ou de l’attribut de quarantaine associé au fichier téléchargé. Ce problème survient notamment avec les outils téléchargés depuis un navigateur, les artefacts copiés depuis une autre session et les caches restaurés à partir d’une archive qui conserve les attributs étendus.
Distinguer d’abord quatre catégories d’échecs d’exécution
Ne supprimez pas les attributs dès qu’un fichier refuse de s’exécuter. Commencez par relever son type, ses autorisations, son architecture et ses attributs étendus. Ces quatre éléments permettent d’écarter la plupart des diagnostics erronés.
TOOL="/opt/build-tools/example-tool"
ls -leO@ "$TOOL"
file "$TOOL"
uname -m
xattr -l "$TOOL"
ls permet de vérifier le propriétaire et les bits d’exécution. La commande file doit indiquer une architecture exécutable compatible avec le nœud. Si xattr affiche com.apple.quarantine, cela signifie uniquement que le fichier est passé par le processus d’évaluation de la quarantaine, et non qu’il est sûr. En cas d’erreur Permission denied, vérifiez d’abord que les répertoires peuvent être traversés et que le point de montage n’interdit pas l’exécution. En cas d’erreur Bad CPU type in executable, utilisez un artefact conçu pour la bonne architecture au lieu de modifier l’attribut de quarantaine.
| Symptôme | Vérification prioritaire | Action à ne pas entreprendre immédiatement |
|---|---|---|
| Permission denied | Autorisations du fichier et des répertoires parents | Supprimer récursivement les attributs étendus |
| Bad CPU type | file et uname -m |
Modifier à répétition les bits d’exécution |
| Fichier endommagé ou invérifiable | Signature et résultat de Gatekeeper | Désactiver les contrôles de sécurité du système |
| Échec limité au runner | Chemin réel, utilisateur et origine du cache | Supposer que l’environnement interactif est identique |
L’attribut de quarantaine renseigne sur l’origine du fichier : il ne constitue pas le problème en lui-même. Vérifiez d’abord qu’il s’agit bien du fichier attendu avant de décider de l’autoriser.
Obtenir le verdict explicite de Gatekeeper
Évaluer un binaire ou une application spécifique
Pour un outil en ligne de commande, contrôlez d’abord la signature, puis demandez au moteur de règles du système de rendre son verdict. Pour une application, remplacez la valeur de TOOL par le chemin du paquet .app correspondant.
codesign --display --verbose=4 "$TOOL"
codesign --verify --deep --strict --verbose=2 "$TOOL"
spctl --assess --type execute --verbose=4 "$TOOL"
Un outil interne non signé n’est pas nécessairement problématique, mais il doit provenir d’un processus de build maîtrisé et son intégrité doit être établie au moyen d’une somme de contrôle. Si un outil tiers précompilé est censé être signé, tout échec de vérification doit conduire à cesser de l’utiliser et à récupérer un artefact fiable. Supprimer l’attribut de quarantaine ne doit jamais servir à masquer une modification de la signature.
Consulter les journaux des règles de sécurité
Les boîtes de dialogue et la sortie d’erreur standard du runner omettent souvent la cause précise. Après avoir reproduit le problème, consultez immédiatement les événements récents des règles de sécurité. Vous pourrez ainsi identifier le chemin réellement évalué et éviter de contrôler le cache A alors que le fichier exécuté provient du cache B.
log show --last 10m \
--predicate 'subsystem == "com.apple.security.syspolicy"' \
--style compact
Comparez méthodiquement le chemin indiqué dans les journaux avec le résultat de command -v, la configuration du runner et les variables des scripts. Les liens symboliques sont une source fréquente d’écarts : le point d’entrée se trouve dans le répertoire des outils, tandis que le fichier final provient d’un ancien cache.
Vérifier l’identité de l’artefact avant de l’autoriser
La méthode la plus sûre consiste à obtenir une somme SHA-256 auprès de l’éditeur de l’outil ou du processus interne de production des artefacts, puis à versionner le fichier de sommes de contrôle avec la configuration de la version de l’outil. Ne calculez pas une somme à partir du fichier téléchargé pour vérifier ensuite ce même fichier. Cette opération prouverait seulement qu’il n’a pas changé entre les deux lectures, sans rien garantir sur son origine.
cd /opt/build-tools
shasum -a 256 -c example-tool.sha256
codesign --verify --deep --strict --verbose=2 example-tool
Un outil compilé en interne peut ne pas disposer d’une signature destinée à la distribution externe. Il faut néanmoins conserver au minimum la révision du code source, la version du script de build et la somme attendue. Si l’outil est fourni sous forme d’archive, vérifiez d’abord cette archive, extrayez-la ensuite dans un répertoire temporaire, contrôlez l’exécutable final, puis remplacez le chemin de production de façon atomique. Le runner ne risquera ainsi pas de lire un fichier incomplet pendant la mise à jour.
Supprimer uniquement l’attribut de quarantaine de la cible
Une fois la somme, la version et la signature confirmées, n’intervenez que sur la cible vérifiée. Commencez par lire la valeur d’origine et par l’inscrire dans le journal de la tâche, puis supprimez uniquement l’attribut concerné.
TOOL="/opt/build-tools/example-tool"
xattr -p com.apple.quarantine "$TOOL" 2>/dev/null || true
if xattr -p com.apple.quarantine "$TOOL" >/dev/null 2>&1; then
xattr -d com.apple.quarantine "$TOOL"
fi
spctl --assess --type execute --verbose=4 "$TOOL"
"$TOOL" --version
N’exécutez pas xattr -cr . dans l’espace de travail. Cette commande supprimerait simultanément plusieurs attributs étendus du dépôt, des dépendances, des scripts et des artefacts temporaires. Elle élargirait inutilement le périmètre autorisé tout en faisant disparaître des indices d’origine utiles à une enquête ultérieure. Un paquet d’application peut effectivement nécessiter la suppression d’attributs hérités par son contenu, mais l’intervention doit rester limitée au paquet individuel déjà vérifié, et non à toute la racine du cache du runner.
Faire de ces contrôles une étape obligatoire de l’installation
Un pipeline CI stable sur un Mac cloud ne doit pas corriger les autorisations à la volée dans chaque tâche de build. Séparez la préparation des outils dans une phase d’installation dédiée : téléchargement dans un répertoire temporaire, contrôle de la somme, vérification de l’architecture, validation de la signature, lecture de l’état de quarantaine, autorisation ciblée, test de la version, puis seulement installation dans le répertoire partagé des outils.
La clé de cache doit contenir au minimum le nom de l’outil, sa version, l’architecture du CPU et sa somme de contrôle. Même en cas de cache valide, effectuez encore un contrôle léger, car son contenu peut avoir été remplacé manuellement. Au démarrage du runner, vous pouvez consigner id -un, uname -m, le chemin résolu de l’outil et sa version, mais pas les identifiants ni l’ensemble des variables d’environnement.
Conservez enfin trois principes en cas d’échec : arrêtez immédiatement si la somme ne correspond pas ; récupérez de nouveau l’artefact si une signature attendue échoue à la vérification ; ne supprimez l’attribut ciblé que lorsque l’évaluation de quarantaine est le seul obstacle à l’exécution d’un artefact déjà vérifié. Cette méthode exige quelques commandes de plus qu’une désactivation globale des contrôles, mais elle rend auditables l’origine de l’outil, l’action d’autorisation et la version réellement exécutée.
Questions fréquentes
Pourquoi macOS bloque-t-il un outil qui possède le droit d’exécution ?
Le droit d’exécution ne couvre que la permission du fichier. Gatekeeper évalue aussi la quarantaine, la signature, la provenance et les règles système ; chmod +x ne modifie pas ces contrôles.
Peut-on lancer xattr -cr sur tout le répertoire de travail CI ?
Non. Cette commande retirerait les attributs de tous les fichiers, y compris ceux qui n’ont pas été vérifiés. Contrôlez d’abord le condensat et la signature, puis retirez uniquement com.apple.quarantine de la cible.
Comment éviter que le même outil soit bloqué à chaque exécution ?
Centralisez le téléchargement, la vérification, l’extraction et l’autorisation ciblée dans une étape d’installation contrôlée, puis indexez le cache par version, architecture et condensat.
Lancez vos builds sur des nœuds physiques Apple Silicon dédiés
Configurez votre nœud selon le modèle, la région et la durée de location. La disponibilité réelle est indiquée en temps réel dans le tableau de bord.