8 min de lecture

L'approbation d'un agent sur macOS doit distinguer chaque build

L'approbation d'un agent sur macOS doit distinguer les builds stable, bêta, de gestionnaire de paquets et locales avant qu'un même processus de confiance ne couvre une autre copie.

L'approbation d'un agent sur macOS doit distinguer chaque build

Approuver un agent IA à partir d'un nom de commande familier revient à approuver le mauvais exécutable. Sur un même Mac, il est facile d'accumuler une version stable de l'éditeur, une bêta, une copie installée par un gestionnaire de paquets et une build compilée depuis les sources, toutes accessibles sous le même nom. Si votre limite d'approbation ne sait pas les distinguer, une décision prise pour une build contrôlée peut s'appliquer discrètement à une autre.

La solution n'est pas une liste d'autorisation plus longue. Vous devez décider quelles propriétés identifient une exécution d'agent dans votre environnement, vérifier que chaque copie installée possède bien ces propriétés, puis tester le comportement de l'approbation lorsque les deux copies sont présentes. Les chemins, les signatures, les designated requirements et les hachages répondent à des questions différentes. C'est en les confondant que les équipes rencontrent des problèmes.

Un même nom de commande peut pointer vers plusieurs exécutables

Une commande shell est un mécanisme de recherche, pas une identité. Lorsque vous saisissez claude, agent ou le nom d'un wrapper, votre shell peut résoudre un alias, une fonction, un shim, un lien symbolique, un répertoire de gestionnaire de paquets ou un fichier placé plus tôt dans PATH que la copie à laquelle vous pensiez.

Commencez dans le terminal, l'éditeur, le service de lancement ou le lanceur d'automatisation qui démarre réellement l'agent. N'inspectez pas un shell interactif pratique en supposant que le résultat sera le même ailleurs. Les shells de connexion, les applications graphiques et les lanceurs CI reçoivent souvent des variables d'environnement différentes.

Exécutez d'abord :

type -a agent-name
command -v agent-name

Vous pourriez obtenir :

agent-name is /Users/me/bin/agent-name
agent-name is /opt/homebrew/bin/agent-name
agent-name is /usr/local/bin/agent-name
/Users/me/bin/agent-name

Cette sortie indique que le premier chemin est prioritaire dans ce shell. Elle ne dit pas si /Users/me/bin/agent-name est un binaire direct, un lien symbolique, un script qui lance un autre binaire ou un wrapper qui modifie les variables d'environnement avant de lui céder le contrôle.

Résolvez le fichier avant de l'inspecter :

BIN="$(command -v agent-name)"
python3 - <<'PY' "$BIN"
import os, sys
print(os.path.realpath(sys.argv[1]))
PY
file "$BIN"

Si file indique un script shell, lisez-le. S'il indique un lien symbolique, inspectez sa destination. S'il indique un exécutable Mach-O universel, inspectez cet exécutable. Un wrapper peut donner une apparence correcte à l'écran d'approbation tout en lançant ensuite un autre processus enfant.

Ne vous arrêtez pas à la copie actuellement prioritaire. Répertoriez tous les résultats de type -a, ainsi que les copies présentes dans le dossier Applications de l'éditeur, dans Téléchargements, dans l'arborescence source et dans les répertoires des gestionnaires de paquets. La copie prioritaire aujourd'hui peut ne plus l'être demain après une mise à jour du gestionnaire de paquets ou une petite modification de PATH.

Un chemin indique un emplacement, pas une identité

Les équipes commencent souvent par une règle de chemin, car les chemins sont faciles à lire. /Applications/Agent.app semble intentionnel. /Users/me/dev/agent/bin/agent semble expérimental. Ce sont des indices utiles, mais un chemin seul ne permet pas d'établir quel code s'y trouve actuellement.

Un gestionnaire de paquets peut remplacer le fichier vers lequel pointe un lien symbolique stable. Un installateur direct peut écraser une app bundle sur place. Une build locale peut réutiliser le même chemin de sortie à chaque compilation. Un attaquant disposant de droits d'écriture suffisants peut remplacer un fichier situé à un chemin approuvé. Le chemin indique seulement où le chargeur l'a trouvé.

Utilisez quatre champs distincts dans votre inventaire :

ChampCe qu'il indiqueCe qu'il ne permet pas de savoir
Chemin résoluOù le lancement a trouvé le fichierQui l'a produit ou s'il a changé
Informations de signatureQuelle identité de signature est associée au codeSi une autre build du même signataire a exactement le même comportement
Designated requirementLa règle de continuité que macOS associe au codeSi la règle est assez précise pour votre objectif d'approbation
Hachage SHA-256Les octets exacts que vous avez inspectésSi une future mise à jour doit hériter de cette confiance

Cette distinction compte parce que chaque champ évolue à un rythme différent. Une mise à jour de l'éditeur peut conserver le chemin et la designated requirement tout en modifiant le hachage. Une bêta peut conserver l'autorité de signature mais utiliser un autre identifiant de bundle. Une build locale peut avoir la même révision source qu'une version publiée tout en portant une signature ad hoc, ou aucune signature.

La note technique Apple TN2206 explique le rôle prévu de la designated requirement : elle doit correspondre aux mises à jour légitimes d'un programme et exclure les autres codes. Elle sert donc de mécanisme de continuité. Elle ne répond pas universellement à la question « est-ce exactement ce binaire que je voulais ? ». Apple précise aussi que la règle par défaut est construite à partir de la configuration de signature. Sa portée dépend donc de la façon dont l'éditeur a signé la build.

Les systèmes d'approbation doivent garder cette séparation. Décider de faire confiance à la prochaine version compatible d'un éditeur n'est pas la même chose que décider de faire confiance à un artefact de version précis. Traiter ces décisions comme identiques empêche d'expliquer ce que l'utilisateur a réellement approuvé.

Inspectez la signature avant de créer une règle d'approbation

Pour chaque exécutable candidat, enregistrez les détails de sa signature et son hachage. Les commandes suivantes utilisent uniquement les outils macOS intégrés et shasum :

inspect_agent() {
  target="$1"
  echo "=== $target ==="
  echo "Resolved path: $(python3 - <<'PY' "$target"
import os, sys
print(os.path.realpath(sys.argv[1]))
PY
)"
  shasum -a 256 "$target"
  codesign --display --verbose=4 "$target" 2>&1 \
    | grep -E '^(Executable|Identifier|TeamIdentifier|Authority|CDHash)='
  codesign --display -r- "$target" 2>&1 \
    | sed -n '/designated/,$p'
  codesign --verify --strict --verbose=2 "$target" 2>&1
}

inspect_agent "$(command -v agent-name)"

La forme de la sortie compte davantage qu'une chaîne particulière de l'éditeur :

=== /opt/homebrew/bin/agent-name ===
Resolved path: /opt/homebrew/Cellar/agent-name/2.4.1/bin/agent-name
3b1f...  /opt/homebrew/bin/agent-name
Executable=/opt/homebrew/bin/agent-name
Identifier=com.example.agent
TeamIdentifier=AB12CDE345
Authority=Developer ID Application: Example, Inc. (AB12CDE345)
CDHash=9c1a...
designated => anchor apple generic and identifier "com.example.agent" and certificate leaf[subject.OU] = "AB12CDE345"
/opt/homebrew/bin/agent-name: valid on disk
/opt/homebrew/bin/agent-name: satisfies its Designated Requirement

Ne considérez pas le CDHash affiché comme un remplacement de votre relevé SHA-256. Le hachage CodeDirectory fait partie du mécanisme de signature et peut varier selon la structure de la signature. shasum -a 256 fournit une empreinte familière du fichier exact pour un relevé de test. En cas de collision suspectée, enregistrez les deux.

Pour une app bundle, inspectez l'exécutable réel plutôt que le seul répertoire du bundle. Trouvez-le ainsi :

APP="/Applications/Agent.app"
EXEC="$APP/Contents/MacOS/$(defaults read "$APP/Contents/Info" CFBundleExecutable)"
inspect_agent "$EXEC"

Si l'agent démarre un processus auxiliaire, inspectez-le également. L'exécutable qui ouvre une fenêtre de terminal n'est pas toujours celui qui effectue les appels HTTP ou lance SSH. Le système d'approbation doit identifier le processus qui demande l'action sensible, tandis que votre test doit vérifier toute la chaîne de lancement.

La TN3127 plus récente d'Apple va plus loin que l'ancien guide de signature : elle montre en quoi les designated requirements par défaut diffèrent selon les types de signature et pourquoi des variantes distribuées séparément peuvent ne pas être compatibles entre elles. C'est une raison de ne pas faire de suppositions. Comparez le texte réel de la requirement de vos fichiers installés.

Les builds stable, bêta, de gestionnaire de paquets et locales exigent une matrice de test

Rendez l'inventaire concret. Choisissez les copies susceptibles d'exister sur votre Mac, donnez à chacune une étiquette courte et notez ce qu'elle doit partager ou non avec les autres.

ÉtiquetteSource habituelleÉtat de signature attenduAttente d'approbation
StableInstallateur de l'éditeur ou app bundleIdentité de signature de publicationCandidate de référence
BêtaCanal bêta de l'éditeurPeut partager l'identité de la version stableÀ tester séparément
Gestionnaire de paquetsFormula, cask, shim de type npm ou équivalentDépend du paquet amontLe véritable exécutable lancé doit être résolu
LocaleArborescence source ou sortie de buildDéveloppement, ad hoc ou non signéeContrôle séparé par défaut

Ce tableau ne dicte pas la bonne réponse. Il empêche la réponse facile qui consiste à supposer qu'un nom de canal suffit. Une bêta peut être signée exactement comme la version stable. Une copie installée par un gestionnaire de paquets peut être un artefact de l'éditeur inchangé, un artefact reconditionné ou un script qui télécharge un autre exécutable. Une build locale peut porter une signature de développement valide qui paraît plus officielle qu'elle ne l'est.

Créez une ligne par copie installée dans un fichier texte conservé avec vos notes de configuration de l'agent :

label: stable
launch path: /Applications/Agent.app/Contents/MacOS/agent-name
resolved path: /Applications/Agent.app/Contents/MacOS/agent-name
version: 2.4.1
identifier: com.example.agent
team or authority: AB12CDE345
sha256: 3b1f...
designated requirement: anchor apple generic and identifier "com.example.agent" ...
expected approval group: release

label: local
launch path: ~/src/agent/build/agent-name
resolved path: /Users/me/src/agent/build/agent-name
version: git revision recorded separately
identifier: ad hoc or absent
team or authority: none
sha256: 8e52...
designated requirement: unavailable or different
expected approval group: local only

Notez la version, mais ne lui confiez pas la décision. Les chaînes de version sont des métadonnées de l'application. Un fichier peut annoncer une version qui ne correspond pas à la publication que vous pensiez avoir téléchargée. La signature et le hachage fournissent des faits indépendants.

Le cas délicat survient lorsque deux lignes ont le même identifiant, la même équipe et la même designated requirement, mais des hachages différents. Ce n'est pas forcément un défaut. Cela signifie que l'éditeur a produit deux builds que macOS peut considérer comme des instances du même programme. Si vous voulez que l'approbation suive le canal de publication de l'éditeur, cela peut convenir. Si elle doit couvrir uniquement un artefact précis, la règle est trop large.

Le mauvais test approuve chaque copie séparément

Suivre chaque exécution d'agent
Le journal Sessions enregistre les exécutions d'agents et permet de révoquer immédiatement une session.

Tester la build stable le lundi et la bêta le mardi ne dit presque rien sur leur couverture mutuelle. Chaque test peut afficher une demande, car aucune approbation active n'existe encore. Vous devez installer les deux copies et garder une session de l'une active pendant que l'autre demande l'accès.

Effectuez cette séquence dans un compte temporaire ou avec des identifiants qui ne peuvent pas modifier les systèmes de production :

  1. Installez les copies stable, bêta, de gestionnaire de paquets et locale. Confirmez leurs chemins résolus et enregistrez le résultat de l'inspection.
  2. Effacez ou révoquez la session d'agent existante avec l'outil d'approbation utilisé. Vérifiez que le prochain appel sensible demandera une nouvelle décision.
  3. Démarrez la copie stable et effectuez un appel inoffensif vers un endpoint de test. N'approuvez que cette exécution. Laissez son processus actif.
  4. Pendant que le processus stable fonctionne, démarrez la copie bêta et effectuez le même appel inoffensif. Vérifiez si elle demande une approbation et inspectez l'identité du processus affichée sur la fiche.
  5. Répétez avec les copies du gestionnaire de paquets et locale. Inversez ensuite l'ordre de PATH et recommencez le test du gestionnaire de paquets.

Le résultat attendu dépend de la règle choisie. Si stable et bêta doivent être séparées, la bêta doit demander une approbation alors que stable reste approuvée. Si elles partagent volontairement un groupe, la fiche et la piste d'audit doivent donner assez de détails pour que ce regroupement soit évident pour un contrôleur.

N'appelez pas une API de production pendant ce test. Utilisez un endpoint de test qui renvoie une réponse fixe et laisse une marque inoffensive et visible dans ses propres journaux. Pour SSH, utilisez un compte de test dont la commande se limite à afficher les informations d'identité :

ssh [email protected] 'id; hostname; date -u +%FT%TZ'

Le test fournit deux observations : ce qu'indique l'écran d'approbation et ce qu'enregistre le système cible. Conservez l'horodatage, le hachage de l'exécutable, l'identifiant du processus et la marque renvoyée. Si un wrapper a modifié l'exécutable réellement lancé, l'écart apparaîtra plus tôt que lors d'une analyse après incident.

Un échec courant ressemble à ceci. Un développeur approuve l'app stable, puis installe une bêta qui ajoute /Users/me/bin avant /Applications à la suite d'une modification de configuration du shell. Le nom de commande reste inchangé. La bêta effectue un appel sans nouvelle demande, car le contrôle d'autorisation reconnaît une identité de signature commune ou un regroupement de processus trop large. Personne ne le remarque, car le processus stable d'origine fonctionne toujours et l'audit indique seulement agent-name. Vous évitez ce problème en imposant le test avec chevauchement, pas en lisant les notes de version.

L'identité du processus et les octets exacts répondent à des questions différentes

Une approbation peut raisonnablement être liée à une identité de processus signé qui reste stable au fil des mises à jour. Elle peut aussi être liée aux octets exacts. Aucun de ces choix n'est universellement correct.

Utilisez l'identité du processus lorsque vous voulez faire confiance à une ligne de publication maintenue par un signataire connu. Vous évitez ainsi de demander une approbation à chaque correctif uniquement parce que le hachage de l'exécutable a changé. Une identité de processus stable peut aussi survivre à un parcours normal de mise à jour.

Utilisez les octets exacts lorsque la build est expérimentale, produite localement, modifiée indépendamment ou issue d'un canal que vous ne voulez pas fusionner avec stable. Le verrouillage par hachage est particulièrement utile pour une enquête ou une reproduction courte, lorsque vous voulez que la décision cesse de s'appliquer dès que le fichier change.

La zone dangereuse consiste à prétendre qu'un identifiant de signature suffit à définir une identité. Apple précise qu'un identifiant de signature peut être revendiqué par plusieurs signataires. Apple recommande de l'associer aux contraintes de validation et d'équipe pertinentes lors de la vérification du code. En pratique, Identifier=com.example.agent sans autorité ni équipe n'est qu'une étiquette que quelqu'un d'autre peut réutiliser.

Une designated requirement est généralement plus forte, car elle peut combiner l'identifiant et des contraintes sur l'autorité de signature. Elle peut toutefois rester plus large que votre intention. Une requirement qui accepte toute build valide signée par une équipe avec un identifiant donné peut couvrir correctement une mise à jour stable, une bêta et une build locale de test produite par l'éditeur. C'est une bonne chose uniquement si vous voulez réellement réunir les trois dans le même groupe d'approbation.

Écrivez la décision de regroupement en termes simples à côté de l'entrée d'inventaire. Par exemple :

Release group: accept future vendor-signed builds with the release identifier.
Beta group: separate, even when signed by the same vendor identity.
Local group: exact SHA-256 only; rebuild requires another approval.

Cette note impose la décision avant que l'interface ne demande un clic. Elle montre aussi si votre outil sait exprimer la distinction. Si ce n'est pas le cas, utilisez une limite opérationnelle plus étroite, comme une approbation par appel pour les builds bêta et locales, jusqu'à ce que l'outil le permette.

L'approbation par session ne remplace pas l'approbation par appel

L'approbation par session répond à la question « ce processus d'agent peut-il fonctionner avec un accès pendant cette exécution ? ». L'approbation par appel répond à la question « cet identifiant précis peut-il être utilisé pour cette action précise maintenant ? ». Le premier contrôle limite le processus qui obtient une session. Le second limite les conséquences de cette session.

Sallyport utilise une échelle de décision fixe : un coffre verrouillé refuse toute action, un nouveau processus d'agent demande normalement une approbation de session et certains identifiants peuvent exiger une nouvelle approbation à chaque utilisation. La fiche d'approbation affiche d'abord l'autorité de signature du processus, ce qui fournit un indice utile, mais il faut tout de même effectuer le test avec chevauchement lorsque plusieurs builds existent.

Utilisez le contrôle le plus fréquent pour les identifiants capables de provoquer des changements irréversibles ou visibles à l'extérieur. Les identifiants de déploiement de production, les API d'administration destructrices et les accès SSH pouvant modifier une infrastructure partagée ne doivent pas hériter de la confiance simplement parce qu'un processus d'agent était acceptable au début d'une longue exécution.

Ne résolvez pas une collision de binaires en marquant tous les identifiants pour une approbation à chaque appel, pour toujours. Vous transformeriez un problème de conception en fatigue d'approbation. Les utilisateurs finissent par approuver les demandes répétitives et prévisibles sans les lire. Séparez plutôt les builds qui ne doivent pas partager l'accès, puis réservez l'approbation par appel aux actions pour lesquelles un humain doit voir le moment précis de l'utilisation.

Pour une passerelle d'action, testez la même matrice à la limite de l'action. Démarrez chaque binaire, faites une requête HTTP de test et une commande SSH de test si les deux canaux sont utilisés, puis comparez l'enregistrement de session et celui de l'appel individuel. Les enregistrements doivent permettre de répondre à trois questions : quel exécutable a lancé la requête, quelle approbation la couvrait et si l'identifiant exigeait une confirmation supplémentaire.

Les gestionnaires de paquets et les shims dissimulent l'exécutable à inspecter

Approuver les nouveaux processus
Un nouveau processus d'agent demande normalement une approbation de session lors de son premier appel.

Les gestionnaires de paquets installent souvent des chemins d'entrée stables qui pointent ailleurs. Une commande située à /opt/homebrew/bin/agent-name peut être un lien symbolique vers un répertoire Cellar versionné. Un autre outil peut installer un shim JavaScript, Python ou shell qui choisit un runtime, puis charge un paquet depuis un répertoire de cache.

Suivez la chaîne jusqu'au processus qui effectue la requête sensible. Ces commandes aident dans les cas courants :

ls -l "$(command -v agent-name)"
readlink "$(command -v agent-name)" || true
head -n 40 "$(command -v agent-name)" 2>/dev/null || true

Sur macOS, readlink peut n'afficher qu'un seul maillon. Le résolveur Python de la première section est plus fiable pour trouver la cible finale. Si le fichier d'entrée est un script, recherchez exec, les appels de runtime, les chemins de binaires téléchargés et les variables d'environnement qui sélectionnent un canal de publication.

Ne supposez pas qu'une version fournie par un gestionnaire de paquets équivaut à la version de l'éditeur portant le même numéro. Le paquet peut appliquer des correctifs, reconditionner un binaire, compiler depuis les sources ou lancer un autre runtime. Traitez l'exécutable installé comme l'élément à approuver et conservez le reçu du paquet comme simple contexte complémentaire.

Le même avertissement vaut pour les extensions d'IDE et les intégrations de terminal. Un lanceur graphique peut embarquer une copie tandis que votre shell en utilise une autre. Testez chaque point d'entrée pouvant démarrer un agent. « Cela demande une approbation correctement dans Terminal » ne prouve rien sur une tâche en arrière-plan lancée par un éditeur.

Les builds locales doivent indiquer clairement qu'elles sont locales

Une build locale est utile précisément parce qu'elle peut différer d'une version publiée. Elle peut contenir un correctif, une mise à jour de dépendance non contrôlée, une modification du compilateur, une option de débogage ou un fichier généré qui n'a jamais intégré l'artefact de l'éditeur. Elle ne doit pas emprunter discrètement la réputation d'approbation de la version publiée.

Commencez par inspecter son état de signature :

LOCAL="$HOME/src/agent/build/agent-name"
codesign --display --verbose=4 "$LOCAL" 2>&1 | sed -n '1,25p'
codesign --verify --strict --verbose=2 "$LOCAL" 2>&1
shasum -a 256 "$LOCAL"

Une sortie non signée, une signature ad hoc et une signature de développement ne sont pas interchangeables. Un exécutable non signé fournit moins d'éléments d'identité durables à la couche d'approbation. Une signature ad hoc peut donner l'impression qu'un fichier est signé sans le relier à une identité de développeur. Une signature de développement identifie un contexte de développement, mais ne transforme pas le fichier en artefact de publication.

La règle par défaut la plus sûre est simple : placez les binaires locaux dans un répertoire séparé, donnez-leur un nom de commande visiblement différent si vous contrôlez la build et exigez une nouvelle approbation chaque fois que le hachage change. Si vous ne pouvez pas renommer la commande, rendez le chemin résolu et l'état de build locale évidents dans votre procédure et vos résultats de test.

Évitez le conseil courant qui consiste à re-signer chaque build locale avec le même certificat que celui des versions publiées pour réduire le nombre de demandes. Ce conseil est populaire parce qu'il simplifie le développement. Il est mauvais lorsque votre modèle d'approbation utilise l'autorité de signature comme limite significative. Vous avez élargi l'identité de publication à chaque machine et chaque script pouvant accéder à ce certificat. Gardez le matériel de signature de publication hors des builds locales ordinaires, sauf si votre processus de publication peut réellement préserver cette garantie.

Les enregistrements d'audit doivent permettre de reconstituer la décision

Bloquer toutes les builds
Quand le coffre Secure Enclave et Touch ID est verrouillé, toute action est refusée.

Un enregistrement qui indique seulement « agent approuvé » constitue une preuve faible. Six semaines plus tard, vous ne pourrez pas savoir si le programme approuvé provenait de l'installateur stable, du dossier bêta, d'un lien symbolique de gestionnaire de paquets ou d'une arborescence locale.

Pour chaque test et chaque changement opérationnel important, conservez :

  • le chemin de lancement et le chemin final résolu
  • l'identifiant de signature, l'autorité ou l'équipe et le texte de la designated requirement
  • le hachage SHA-256 et la version de l'application
  • l'identifiant du processus, l'heure de démarrage et le résultat de la session
  • la cible de l'action et le résultat de l'appel individuel

Sallyport conserve les exécutions d'agents dans son journal Sessions et les actions individuelles dans son journal Activity, tous deux produits à partir d'un journal d'audit chiffré et chaîné par hachage. Son contrôle hors ligne sp audit verify peut confirmer que la chaîne du journal chiffré est toujours valide, mais l'intégrité du journal ne complète pas les champs d'identité que vous n'avez jamais enregistrés. Ajoutez les éléments relatifs à l'exécutable au contexte de l'événement pendant que vous pouvez encore inspecter la machine.

Effectuez une vérification d'audit après avoir modifié la matrice des builds, révoqué une session et répété le test avec chevauchement. Vous devez confirmer deux choses : le système a enregistré les exécutions distinctes attendues et la piste d'enregistrement reste valide lorsqu'elle est lue indépendamment. Une chaîne intacte prouve la continuité du relevé, pas que votre décision initiale de regroupement était judicieuse.

Transformez cette procédure en test de régression

Les copies multiples reviennent. Quelqu'un installe une bêta pour tester un correctif. Un gestionnaire de paquets se met à jour pendant la nuit. Un collègue partage une build locale. L'app stable se met à jour sur place. Si vous ne testez qu'après un incident, vous découvrirez la collision alors que l'agent possède déjà l'accès.

Conservez un court script qui écrit un rapport horodaté pour chaque chemin candidat. Exécutez-le après les changements d'installation, avant d'accorder un identifiant à fort impact et chaque fois que vous modifiez les fichiers de démarrage du shell ou les réglages d'agent de l'éditeur.

#!/bin/zsh
set -eu

for candidate in \
  "/Applications/Agent.app/Contents/MacOS/agent-name" \
  "/opt/homebrew/bin/agent-name" \
  "$HOME/src/agent/build/agent-name"; do
  [[ -e "$candidate" ]] || continue
  echo "### $candidate"
  echo "resolved: $(python3 -c 'import os,sys; print(os.path.realpath(sys.argv[1]))' "$candidate")"
  shasum -a 256 "$candidate"
  codesign --display --verbose=4 "$candidate" 2>&1 \
    | grep -E '^(Identifier|TeamIdentifier|Authority|CDHash)=' || true
  codesign --display -r- "$candidate" 2>&1 \
    | grep 'designated' || true
  echo
 done

Comparez le rapport avec la dernière copie contrôlée. Un hachage différent est normal après une mise à jour. Une autorité de signature, un identifiant ou une designated requirement différents nécessitent une décision explicite avant que vous ne traitiez la modification comme une mise à jour ordinaire. Un nouveau chemin qui apparaît avant le chemin de publication dans type -a mérite la même attention.

La règle pratique est simple : une approbation doit s'appliquer au groupe d'exécutables que vous avez choisi, et vos éléments de preuve doivent montrer pourquoi ce groupe inclut une build et en exclut une autre. Installez les copies stable, bêta, de gestionnaire de paquets et locale sur le même Mac, gardez un processus approuvé en fonctionnement et forcez chaque autre copie à demander son propre accès. Si le résultat vous surprend, la limite d'approbation est trop vague.

FAQ

Puis-je faire confiance à une approbation d'agent qui affiche seulement le nom du processus ?

Non. Le nom d'un processus ne dit presque rien sur l'auteur de l'exécutable ni sur sa correspondance avec le programme que vous vouliez approuver. Considérez-le comme une étiquette destinée aux humains, puis vérifiez le chemin, la signature, la designated requirement et le hachage de l'exécutable.

Les versions stable et bêta d'un agent doivent-elles partager une approbation sur macOS ?

En général, non. Les builds stable et bêta peuvent partager un identifiant de bundle, un nom de commande et une autorité de signature, notamment lorsque le même éditeur fournit les deux. Testez-les séparément avant de décider qu'une approbation doit couvrir l'autre.

Une installation par gestionnaire de paquets constitue-t-elle une identité d'agent distincte ?

Une installation Homebrew n'est pas automatiquement plus sûre ou plus distincte qu'un téléchargement direct. La question importante est de savoir quel exécutable votre shell lance et quelle identité de signature et quel hachage il possède après l'installation.

Dois-je approuver un binaire d'agent compilé localement ?

Une build locale doit normalement faire l'objet de son propre contrôle, sauf si vous faites délibérément confiance à son identité de signature et à son processus de build. Une signature ad hoc, une signature de développement ou un exécutable non signé n'offre pas le même niveau de garantie qu'une version publiée.

Comment trouver toutes les copies d'une commande d'agent sur mon Mac ?

Commencez par type -a agent-name, puis inspectez chaque chemin retourné avec codesign et shasum. Faites-le dans l'environnement de terminal exact qui démarre l'agent, car l'ordre de PATH et les fonctions du shell peuvent modifier le résultat.

Qu'est-ce qu'une designated requirement dans la signature de code macOS ?

Une designated requirement décrit les conditions utilisées par macOS pour reconnaître du code signé comme appartenant au même programme au fil des mises à jour. Elle comprend souvent un identifiant de signature et une autorité de signature. Elle est donc utile pour assurer la continuité, mais peut être trop large si vous voulez séparer les canaux de publication.

L'autorité de signature suffit-elle à identifier un exécutable ?

Une autorité de signature indique qui a signé l'exécutable. Elle ne prouve pas que deux fichiers sont identiques octet par octet. Associez-la donc au hachage de l'exécutable lorsque vous devez distinguer des builds provenant du même signataire.

Comment vérifier qu'une approbation couvre le mauvais exécutable ?

Le test pratique est simple : laissez une copie approuvée fonctionner, démarrez l'autre et vérifiez si la limite d'approbation se comporte comme prévu. Recommencez après avoir révoqué la première session et après avoir modifié l'ordre de PATH.

Quand faut-il demander une approbation pour chaque appel de l'agent ?

Utilisez l'approbation par appel pour les identifiants capables de modifier des données de production, d'exposer des données client ou d'atteindre des systèmes hors de votre environnement de développement habituel. L'approbation de session convient mieux à une exécution d'agent contrôlée dont les actions autorisées ont un impact limité.

Que faut-il enregistrer pour chaque build d'agent approuvée ?

Conservez un inventaire simple avec le chemin de l'exécutable, sa source d'installation, sa version, son identifiant de signature, son équipe ou son autorité, sa designated requirement et son hachage SHA-256. Actualisez-le après l'installation d'une bêta, la mise à jour d'un gestionnaire de paquets ou une nouvelle compilation depuis les sources.

Sallyport

Sallyport exécute les appels d'API et les commandes SSH à la place de votre agent IA. Les clés restent dans un coffre-fort local sur votre Mac ; vous approuvez chaque exécution et chaque action est consignée dans un journal scellé.

© 2026 Sallyport · Open source sous Apache-2.0 · Oleg Sotnikov