# L'approbation de session lors d'un remplacement de processus survit-elle à exec ?

Une approbation de session doit suivre une identité d'exécution vérifiée, et non un identifiant de processus du système d'exploitation. Lorsqu'un processus appelle `exec`, le noyau peut conserver son PID tout en remplaçant le code, les arguments, l'environnement et souvent la finalité pratique du processus. Laisser l'ancienne approbation survivre à ce remplacement donne à du code non contrôlé l'autorité qu'une personne avait accordée à autre chose.

La règle que je mettrais en production est simple : lorsqu'un remplacement présente une identité d'exécutable différente, il doit redemander une approbation avant toute action nécessitant des identifiants. Préservez la continuité uniquement lors d'un `re-exec` strictement vérifié de la même image exécutable. Cette politique crée parfois une demande supplémentaire dans un flux légitime. Elle ferme une faille bien plus grave dans tous les flux où un agent, un wrapper, un programme de mise à jour ou une dépendance compromise peut choisir ce qui s'exécute ensuite.

## Une approbation lie un acteur, pas un PID

Un PID identifie une case de gestion du noyau, tandis qu'une approbation doit identifier le programme capable d'utiliser une décision humaine. Ces deux fonctions sont différentes, et les confondre pose problème dès qu'un programme en démarre un autre.

Sallyport décrit l'autorisation par session comme une approbation accordée à un nouveau processus agent et valable jusqu'à la fin de cette exécution. C'est une règle claire pour l'utilisateur, mais l'implémentation a besoin d'une définition interne plus précise : l'exécution approuvée doit rester celle de l'exécutable approuvé, au lieu de simplement conserver le même PID.

Cette différence compte parce que les secrets restent dans la passerelle et que l'agent reçoit des résultats, pas les identifiants eux-mêmes. Cette conception écarte le scénario classique où un processus enfant lit un jeton dans une variable d'environnement. Elle n'empêche pas un processus substitué de demander à la passerelle d'appeler une API ou d'exécuter SSH avec un identifiant conservé. Si ce processus substitué hérite de l'approbation, il peut causer le même dommage externe sans jamais voir le secret.

Rendez le sujet de l'approbation explicite. Il doit inclure une identité d'exécutable stable, l'événement de création du processus ou un nonce de session, l'autorité de signature du code présentée à la personne et suffisamment de contexte de lancement pour expliquer pourquoi le processus existe. Utilisez le PID comme attribut d'audit et comme aide utile au dépannage. N'en faites pas l'identifiant d'autorisation.

Cette distinction rend aussi la révocation fiable. Si un utilisateur révoque une exécution, la passerelle doit refuser les appels ultérieurs de cette exécution, même si elle se réexécute avec `exec`. Si un remplacement reçoit une nouvelle approbation, il doit obtenir une nouvelle fiche de session que l'utilisateur peut révoquer indépendamment.

## `exec` change l'exécutable même si le PID reste le même

`exec` doit réinitialiser l'autorisation lorsqu'il charge un autre programme, car il remplace l'image du programme même si le système d'exploitation conserve le PID. POSIX indique qu'une fonction exec « remplace l'image du processus courant ». La formulation est courte, mais elle exprime l'essentiel : la continuité est administrative, elle ne prouve pas que le même acteur est toujours présent.

Un shell permet facilement de ne pas voir cette différence. Un développeur démarre un agent approuvé, l'agent appelle un outil auxiliaire et celui-ci utilise `exec` pour éviter de laisser un processus parent supplémentaire. Les listes de processus peuvent afficher le même PID avant et après le remplacement. Si votre recherche de session indique que `pid 4127 est approuvé`, le nouvel outil auxiliaire possède alors l'autorité de l'ancien agent.

Le changement d'exécutable peut aussi modifier le risque d'une manière qu'un PID ne peut pas décrire. Le remplacement peut communiquer avec un autre hôte, interpréter un fichier non fiable d'un dépôt, charger des extensions, accepter des données sur l'entrée standard ou exister uniquement pour relayer des demandes d'action. Aucun de ces faits n'apparaît dans un numéro de processus.

Ne fondez pas la décision sur l'apparence familière de la nouvelle ligne de commande. Les arguments sont un contexte utile, mais un programme peut les réécrire et un wrapper peut faire lancer une cible sans rapport avec une commande apparemment inoffensive. Établissez l'identité de l'exécutable à partir de l'image réellement démarrée par le système d'exploitation, puis conservez le chemin et les arguments observés comme éléments permettant à la personne d'examiner la demande.

`posix_spawn` doit être abordé dans la même conception, mais son résultat est différent. Il crée un processus enfant au lieu de remplacer l'image du processus appelant. Par défaut, l'enfant ne doit recevoir aucune approbation de session. Un `fork` suivi d'un `exec` doit aboutir au même résultat : le nouveau processus demande une approbation pour l'image qui s'exécute finalement.

## Un nouvel exécutable a besoin d'une nouvelle approbation

Une passerelle doit exiger une nouvelle approbation avant qu'un exécutable différent puisse effectuer une action via une session déjà autorisée. Définissez la différence à partir d'une identité d'image vérifiée, et non d'un nom de fichier ou d'un nom affiché.

Une fiche d'identité pratique peut contenir l'identifiant immuable de l'exécutable fourni par la plateforme, le condensé du code signé lorsqu'il est disponible, l'autorité de signature et le chemin concret de l'exécutable observé au lancement. Les deux premiers éléments indiquent si l'image a changé. Le signataire indique à la personne qui répond du code. Le chemin indique d'où vient le lancement. Chaque champ répond à une question différente, ne les réduisez donc pas à une seule chaîne.

C'est le type d'échec qui rend l'héritage permissif séduisant jusqu'à ce qu'il soit trop tard. Un agent de programmation approuvé appelle un outil auxiliaire du dépôt. L'outil voit un paramètre d'environnement et se remplace par un utilitaire compilé localement au même chemin attendu. L'utilitaire n'a pas besoin d'extraire un identifiant API. Il demande une action HTTP qui supprime un déploiement, modifie un paramètre de facturation ou publie une version. La passerelle voit l'ancien PID et accepte l'appel. La personne a approuvé l'agent de programmation, pas l'utilitaire qui s'est choisi lui-même après l'approbation.

L'argument habituel en faveur de l'héritage de l'approbation est la fatigue liée aux demandes. Cette préoccupation est légitime, mais autoriser n'importe quel remplacement ne la résout pas. Cela masque une décision à la personne qui peut juger si le remplacement est cohérent. Gardez les cartes d'approbation rares en stabilisant l'exécution normale de l'agent, puis redemandez l'accord au moment où l'acteur change.

La vérification doit avoir lieu avant l'injection d'identifiants, l'exécution SSH ou toute autre action sortante. Elle doit aussi avoir lieu avant que la passerelle ne renvoie des métadonnées susceptibles d'aider un remplacement à préparer une action. Une approbation en attente n'est pas un état partiellement autorisé.

## Le `re-exec` de la même image est l'exception étroite

Un `re-exec` vérifié de la même image exécutable peut conserver l'approbation de session, puisqu'il n'introduit pas de nouvel acteur. Les programmes utilisent un `re-exec` pour redémarrer proprement, modifier des descripteurs de fichiers ou effectuer un passage de relais délibéré après avoir mis à jour leur environnement. Imposer une nouvelle carte dans ce cas ajoute du bruit sans créer de décision utile.

Gardez cette exception étroite. La passerelle doit comparer l'image actuellement observée à celle qui a reçu l'approbation. Si l'identité est identique, elle peut conserver le nonce de session et écrire un événement de continuité dans le journal d'audit. Si la passerelle ne peut pas établir cette identité, elle doit redemander l'approbation. L'ambiguïté ne prouve pas que le remplacement est sûr.

N'en faites pas une exception valable pour tout un signataire. Un même signataire peut publier un agent, un installateur, un outil de diagnostic et un utilitaire réseau. Ces programmes peuvent avoir des autorités d'action très différentes. L'autorité de signature affichée aide l'utilisateur à évaluer la demande, mais elle ne doit pas étendre silencieusement l'approbation à tous les binaires qui portent cette même autorité.

N'en faites pas non plus une exception valable pour tout un chemin. Une mise à jour automatique peut remplacer les octets d'un chemin fixe. Un lien symbolique peut pointer ailleurs après l'approbation. Un script peut conserver son nom alors que son contenu change. La comparaison d'identité doit résister à ces trois cas.

Lorsqu'une mise à jour légitime installe une nouvelle version de l'agent, laissez-la redemander l'approbation. Cette demande communique un fait réel : l'exécutable qui va agir a changé. Un utilisateur qui considère la mise à jour comme normale peut l'approuver en un clic. Celui qui ne s'attendait pas à ce changement peut l'arrêter.

## L'autorité de signature aide à évaluer le code, mais n'accorde pas de périmètre

Affichez clairement l'autorité de signature du code, car elle répond à une vraie question : qui a publié cet exécutable ? Ne confondez pas cette réponse avec une règle d'autorisation complète.

Le modèle de signature du code d'Apple permet à macOS d'identifier le code signé et d'en vérifier l'intégrité selon les règles de confiance applicables. C'est un élément important pour la carte d'approbation. Il n'indique pas que tout le code d'une même autorité a le même objectif opérationnel et ne dit pas à la passerelle si un processus parent a sélectionné l'exécutable via un paramètre non fiable d'un dépôt.

Une bonne carte d'approbation place d'abord le nom et le chemin de l'exécutable, puis l'autorité de signature, l'identité du parent et la raison de la nouvelle demande. Pour un remplacement par `exec`, elle doit présenter les deux côtés du changement en une phrase : l'agent approuvé s'est remplacé par cet exécutable. La personne ne devrait pas avoir à déduire la transition en comparant deux demandes séparées.

Les cas signés et non signés doivent respecter la même limite. Une version locale non signée destinée au développement peut être normale dans un flux de travail, et un utilitaire signé peut tout de même être le mauvais processus auquel transmettre une autorité. La carte doit décrire les éléments disponibles sans prétendre qu'une signature transforme un nouvel exécutable en ancien exécutable.

Évitez les libellés vagues comme « processus de confiance ». Ils incitent à approuver une catégorie plutôt qu'une demande concrète. Nommez l'exécutable et montrez sa relation avec le processus déjà approuvé. Vous donnez ainsi à la personne un élément qu'elle peut reconnaître ou refuser.

## Les scripts et les lanceurs révèlent la faiblesse de la limite

Un lancement piloté par un script nécessite deux identités : celle de l'interpréteur qui l'exécute et celle du script dont le contenu le contrôle. Si vous n'examinez que l'interpréteur, tous les scripts shell semblent utiliser le même shell. Si vous n'examinez que le script, vous pouvez manquer un interpréteur sélectionné par une ligne shebang ou un wrapper.

Pour un script shell, enregistrez l'identité de l'exécutable interpréteur, le chemin résolu du script et un condensé de son contenu. Si le script s'exécute via un shell approuvé puis que ce shell utilise `exec` pour lancer un autre binaire, le remplacement du binaire nécessite tout de même une nouvelle approbation. Un script ne doit pas devenir un tunnel qui traverse la limite de session.

Les lanceurs créent un problème similaire. Un lanceur approuvé peut examiner un fichier de configuration, découvrir un outil dans `PATH`, télécharger un outil auxiliaire ou choisir un répertoire de version. Il est courant d'approuver le lanceur et de considérer sa cible comme faisant partie de la même exécution. Cette règle est incorrecte lorsque le lanceur prend la décision importante pour la sécurité après l'approbation de l'utilisateur.

Utilisez l'une de deux approches. Si le lanceur connaît sa cible avant son premier appel à la passerelle, affichez la cible finale sur la carte et approuvez cette identité d'exécution. Si le lanceur choisit plus tard, laissez-le s'exécuter sans autorité d'action et demandez une approbation lorsque la cible sélectionnée demande pour la première fois à agir. La seconde option produit une trace d'audit plus fidèle.

La même règle s'applique aux modules d'extension et aux interpréteurs intégrés. Un hôte natif peut rester inchangé tout en chargeant du code depuis le répertoire d'un projet. Si ce code chargé peut formuler des demandes à la passerelle, l'identité de l'image de l'hôte ne décrit pas à elle seule l'acteur réel. La passerelle ne peut pas inspecter chaque environnement d'exécution en toute sécurité. La valeur par défaut la plus sûre consiste donc à limiter l'approbation de session à un exécutable agent défini et à exiger une nouvelle décision lorsqu'il cède le contrôle des actions à un programme externe.

## Les processus enfants et `exec` sont deux cas de délégation différents

Un processus enfant ne doit pas hériter de l'approbation de session simplement parce que son parent la possède. La création d'un processus introduit un nouvel acteur, tandis que `exec` remplace l'acteur courant. Dans les deux cas, une nouvelle approbation est nécessaire lorsqu'un exécutable différent effectuera des appels à la passerelle, mais les relations d'audit ne sont pas les mêmes.

Pour un enfant, créez un nouveau candidat de session avec une référence à la session parent. Affichez le parent sur la carte d'approbation, car il fournit un contexte utile, et non parce qu'il accorde une permission. Si l'utilisateur approuve l'enfant, donnez-lui son propre nonce de session et son propre mécanisme de révocation.

Pour `exec`, fermez ou remplacez l'identité de l'ancien exécutable et créez un candidat de remplacement lié à la session précédente. Si la nouvelle image correspond exactement à l'image approuvée, conservez la continuité et inscrivez ce résultat. Si elle diffère, arrêtez-vous à la passerelle et attendez une décision. Vous évitez ainsi une énorme fiche de session contenant plusieurs programmes sans rapport.

Ne créez pas de jeton de délégation général qu'un parent pourrait transmettre à des enfants ou à des remplacements. Un jeton qui signifie « tout ce que je démarre peut agir » devient une cible facile pour un agent compromis ou un wrapper confus. Une référence au parent dans le journal suffit à raconter l'histoire sans transformer l'ascendance en autorité.

Cette séparation améliore aussi l'analyse des incidents. Vous pouvez savoir si le parent a démarré un enfant, s'il s'est remplacé lui-même et si une personne a approuvé l'exécutable obtenu. Un relevé plat des demandes autorisées ne permet pas de répondre à ces questions après une action malveillante.

## Enregistrez le remplacement comme son propre événement

Un journal d'audit doit afficher un remplacement par `exec` comme un événement distinct, que la passerelle ait conservé l'approbation ou ait redemandé l'accord. Sans cet événement, la personne qui examine le journal voit des actions provenant d'une même session et peut supposer qu'un seul exécutable stable les a toutes effectuées.

Un contrat de conception peut ressembler à ceci. Il s'agit d'un exemple des informations à conserver, et non d'un format d'échange obligatoire :

```json
{
  "event": "execution_replaced",
  "session_id": "sess_8f2c",
  "previous_image": {
    "identity": "image:4f19...",
    "path": "/work/agent/bin/agent"
  },
  "current_image": {
    "identity": "image:b66a...",
    "path": "/work/agent/bin/release-helper",
    "signing_authority": "Example Development Team"
  },
  "decision": "approval_required",
  "parent_relation": "exec"
}
```

L'événement doit contenir les identités précédente et actuelle, et pas seulement indiquer qu'un `exec` a eu lieu. Il doit aussi contenir le résultat de la décision. Une fiche d'action ultérieure doit faire référence à l'identité de session actuelle afin que l'enquêteur puisse relier l'action à l'approbation qui l'a autorisée.

Conservez cet enregistrement en ajout uniquement, avec le reste de l'historique des actions. Le journal d'audit chiffré et chaîné par hachage de Sallyport ainsi que la vérification hors ligne `sp audit verify` sont particulièrement utiles ici, car l'événement de remplacement et les actions qui le suivent peuvent partager une même séquence vérifiable. Le résultat de la vérification établit que la séquence stockée n'a pas changé. Il ne rend pas acceptable une politique d'approbation trop large.

Lorsqu'un utilisateur révoque une session, enregistrez la révocation contre l'identité de l'exécutable qui détenait la session. Si un remplacement a reçu une nouvelle approbation, il doit rester visible séparément. Ce détail empêche un contrôle de révocation de laisser croire à une couverture plus large qu'elle ne l'est réellement.

## Une carte d'approbation doit présenter l'avant et l'après

Après un `exec`, une carte de nouvelle approbation doit expliquer le remplacement en un coup d'œil et faciliter un choix sûr. Les demandes génériques habituent les utilisateurs à cliquer sans regarder. Une carte qui nomme l'exécutable modifié leur donne une raison de s'arrêter uniquement lorsqu'un changement a eu lieu.

Commencez par l'identité du nouvel exécutable et le canal d'action qu'il veut utiliser. Indiquez ensuite qu'un processus déjà approuvé l'a lancé, le nom et le chemin de l'ancien exécutable, le nouveau chemin et l'autorité de signature du code. Si le remplacement provient d'un script ou d'un lanceur, décrivez cette relation en termes simples.

Utilisez un modèle de décision qui montre exactement ce que l'utilisateur approuve. Approuver le remplacement doit autoriser l'exécution de cet exécutable jusqu'à sa fermeture, sous réserve de la passerelle du coffre et de tout identifiant marqué pour une approbation à chaque appel. Cela ne doit pas autoriser rétroactivement les processus frères, les futurs remplacements ou un fichier mis à jour au même chemin.

Voici un test utile pour la formulation : un développeur fatigué peut-il faire la différence entre un outil auxiliaire attendu et un programme de téléchargement inattendu ? Si ce n'est pas le cas, la carte ne contient pas les informations importantes. Un vocabulaire de sécurité plus décoratif ne corrigera pas ce problème.

Gardez le nombre de demandes bas grâce à une exécution stable, et non à un héritage trop large. Un agent normal qui conserve une seule image doit afficher une seule carte de session. Un processus qui change d'acteur doit afficher une carte, car il a franchi la limite précise que le concept de session existe pour faire respecter.

## Construisez vos tests autour des contournements réellement utilisés

Testez la limite d'autorisation avec des remplacements qui conservent les identifiants superficiels. Les tests nominaux avec un binaire stable ne détecteront pas les erreurs qui transmettent l'autorité au mauvais exécutable.

Commencez par ces cas :

- Un binaire approuvé exécute un `re-exec` vers une copie exacte de lui-même. La passerelle conserve la session et enregistre un événement de continuité.
- Le binaire exécute un `re-exec` vers un exécutable signé différent de la même autorité. La passerelle refuse les actions jusqu'à ce que la personne approuve la nouvelle exécution.
- Un lien symbolique conserve la même chaîne de chemin mais pointe vers un exécutable différent. La passerelle redemande l'approbation.
- Un script shell change de contenu après le début de la session. La prochaine demande contrôlée par le script ne réutilise pas la décision précédente.
- Un lanceur démarre un enfant et celui-ci tente une action HTTP ou SSH. L'enfant a besoin de sa propre décision de session.

Testez ensuite l'ordre des opérations. Faites envoyer une demande d'action par le remplacement immédiatement après `exec`. Vérifiez que la passerelle la refuse ou la maintient en attente, et confirmez qu'aucune injection d'identifiants ni exécution SSH ne commence avant l'arrivée du résultat de l'approbation. Cela permet de détecter les implémentations qui ne mettent à jour leur journal qu'après avoir déjà lancé l'action.

Testez la révocation dans la même suite. Révoquez une exécution approuvée, tentez un `re-exec` de la même image et confirmez que l'état révoqué l'emporte. Approuvez un nouveau remplacement, révoquez uniquement la session d'origine et vérifiez que les deux fiches se comportent conformément aux contrôles annoncés par le produit. Un modèle de session inspire confiance lorsque ses cas limites correspondent à ce que son interface promet.

Enfin, examinez la sortie d'audit comme le ferait une personne. Vous devez pouvoir remonter d'une action à un événement de remplacement, puis à la carte d'approbation qui couvrait l'exécutable. Si cette réponse exige de mettre en relation des PID, de deviner à partir des horodatages ou de faire confiance à un chemin qui a pu changer, le modèle présente encore une faille.

Un remplacement de processus est le moment où il faut être strict. L'ancien code avait une décision. Le nouveau code doit avoir la sienne.
