# Révoquer en toute sécurité l'accès d'un agent IA pendant une tâche active

Un agent IA actif n'a pas besoin d'intentions malveillantes pour provoquer un incident. Une mauvaise instruction, une autorisation trop large pour un outil, un fichier empoisonné dans un dépôt ou un opérateur désorienté peuvent l'entraîner dans une boucle destructive alors qu'il dispose encore de ses accès. La réponse doit empêcher rapidement toute nouvelle action sans jeter les traces qui permettent de comprendre ce qui s'est passé.

La mauvaise réaction habituelle consiste à fermer le terminal, à révoquer tous les identifiants disponibles et à reconstituer l'événement de mémoire le lendemain matin. Cela crée une panne plus importante et efface souvent la distinction entre ce que l'agent a tenté, ce qu'un service distant a accepté et ce qui a réellement changé. Traitez un incident impliquant un agent comme une opération de confinement avec gestion des preuves, pas comme une interruption embarrassante à dissimuler.

## La révocation doit bloquer l'autorité future avant d'effacer la scène

Révoquer un agent signifie l'empêcher d'effectuer sa prochaine action privilégiée tout en conservant assez d'état pour déterminer si ses actions précédentes ont réussi. Tuer une fenêtre de conversation ou de terminal visible peut ne répondre à aucune de ces exigences. Le processus peut avoir des processus enfants, l'agent peut conserver une connexion distante ouverte et une requête HTTP peut continuer après la disparition du processus local.

Séparez ces quatre éléments avant de toucher aux contrôles :

- Le processus de l'agent est le programme local qui génère les décisions et les appels d'outils.
- La session est l'autorité accordée à cette exécution précise du processus.
- L'identifiant est le secret ou l'identité accepté par un système externe.
- L'opération distante est le travail déjà accepté par une API, une file d'attente, un hôte ou un plan de contrôle cloud.

Les équipes confondent régulièrement révocation de session et rotation des identifiants. Les conséquences peuvent être importantes. Si vous faites tourner un jeton de déploiement partagé pour arrêter un agent, vous risquez de casser l'automatisation de production alors que la requête déjà acceptée par l'agent continue son exécution. Si vous tuez seulement le processus de l'agent après qu'il a copié un jeton dans un espace de travail, vous risquez de laisser derrière vous un secret réutilisable.

Le confinement doit donc suivre le contrôle fiable le plus proche de l'agent. Refusez d'abord l'exécution active. Arrêtez ou annulez ensuite le travail passé dans les systèmes distants. Passez à la désactivation des identifiants lorsque les preuves indiquent que le secret n'est peut-être plus confiné, ou lorsque vous ne pouvez pas vous fier à la frontière de session.

Écrivez à l'avance une règle d'incident simple : la personne qui observe un comportement suspect peut arrêter l'agent immédiatement, sans attendre une réunion. L'analyse vient ensuite. Un processus d'approbation retardé convient à un déploiement, pas au retrait de l'autorité d'un processus actif.

## Construisez une cartographie des actions avant le premier incident

Vous ne pouvez pas révoquer ce que vous ne pouvez pas identifier. Chaque exécution d'agent doit avoir un identifiant présent dans son enregistrement de processus local, ses journaux d'outils et les requêtes qui atteignent les systèmes distants. Un identifiant d'exécution aléatoire suffit si vous le transmettez partout de manière cohérente. N'utilisez pas un nom humain ni une étiquette vague comme `coding-agent` : ces choix mélangent des activités sans rapport dans le même ensemble.

Pour chaque route par laquelle un agent peut agir, consignez les réponses à cinq questions opérationnelles :

1. Quel processus local possède cette route et comment l'arrêter ?
2. Quelle session ou quel jeton représente ce processus auprès de la passerelle d'action ?
3. Quelles opérations distantes peuvent rester actives après la révocation locale ?
4. Où des journaux de service indépendants enregistrent-ils ces opérations ?
5. Qui peut désactiver cette route lorsque son responsable habituel n'est pas disponible ?

Ce n'est pas de la paperasse gratuite. Pendant un incident, un opérateur ne devrait pas avoir à découvrir si une migration de base de données passe par un processus shell enfant, une tâche CI, une requête HTTP ou un flux de travail cloud distinct.

Utilisez un identifiant d'exécution comme en-tête de requête partout où une API l'autorise. Pour un agent dont l'identifiant d'exécution est `run_2025_04_18_7f3c`, un wrapper peut ajouter un en-tête de corrélation sans placer de secret dans l'invite ou l'environnement de l'agent :

```sh
export AGENT_RUN_ID="run_2025_04_18_7f3c"
curl -sS -X POST "$ACTION_ENDPOINT" \
  -H "X-Agent-Run-ID: $AGENT_RUN_ID" \
  -H "Content-Type: application/json" \
  --data @request.json
```

Le service destinataire doit journaliser l'identifiant d'exécution avec son identifiant de requête habituel, l'identité de l'appelant, le point de terminaison, le statut de réponse et l'heure. Un enregistrement utile peut avoir cette forme :

```text
time=2025-04-18T14:12:09Z request_id=req_91a run_id=run_2025_04_18_7f3c caller=agent-gateway method=POST path=/deployments status=202
```

Un statut `202` est important. Il signifie que le service a accepté le travail, pas que celui-ci est terminé. C'est souvent là que les analyses d'incident se trompent : les équipes considèrent la dernière sortie d'outil de l'agent comme le résultat, alors que le système distant n'a fait qu'accuser réception d'une soumission dans une file.

Pour SSH, cartographiez le compte distant, les hôtes cibles, les commandes forcées éventuelles et l'emplacement qui enregistre les connexions et les commandes. Une transcription du terminal local est utile, mais elle ne prouve pas qu'une commande n'a pas été exécutée à distance. Les journaux de l'hôte et la piste d'audit du service concerné permettent de trancher.

## Arrêtez l'exécution active dans un ordre qui conserve le contrôle

Commencez par noter l'heure et la raison immédiate de la révocation, puis refusez les nouvelles actions et terminez l'agent. Les commandes exactes varient selon le système d'exploitation et l'environnement d'exécution, mais la séquence ne devrait pas changer, car elle sépare le confinement du nettoyage.

1. Notez l'identifiant d'exécution, l'identifiant du processus local, l'opérateur, le comportement observé et l'heure actuelle dans le dossier d'incident. Copiez la transcription actuelle de l'agent et le dernier appel d'outil visible avant de fermer son interface.
2. Révoquez ou verrouillez la session active auprès de la passerelle qui autorise les actions. Confirmez qu'un nouvel appel de test provenant de ce même processus est refusé, si une opération de lecture sans risque est disponible.
3. Suspendez le processus local avant de le tuer lorsque le système d'exploitation le permet. La suspension vous donne un arbre de processus et une liste de fichiers ouverts stables. Ne le tuez qu'après avoir capturé cet état, sauf si la poursuite de son exécution causerait un dommage immédiat.
4. Trouvez et arrêtez les processus enfants, tâches en arrière-plan, conteneurs et sessions distantes liés à cette exécution.
5. Annulez le travail distant accepté à l'aide du mécanisme d'annulation du service, puis conservez la réponse et le statut.

Sur macOS ou Linux, commencez par une inspection plutôt que par un `kill -9` aveugle. Remplacez l'identifiant de processus fourni en exemple par celui que vous avez enregistré :

```sh
ps -o pid,ppid,pgid,lstart,command -p 48192
pgrep -P 48192 -a
lsof -nP -p 48192
kill -STOP 48192
```

La première commande enregistre la parenté et l'heure de démarrage. `pgrep` révèle les enfants directs et `lsof` affiche souvent les fichiers d'espace de travail ouverts, les sockets et les tubes qu'il est utile de préserver. `kill -STOP` fige un processus coopératif sans lui donner une nouvelle occasion d'exécuter une commande de nettoyage. Il ne fige pas un enfant déjà détaché, une tâche distante ni une requête API qui a franchi la frontière réseau.

Après avoir copié les sorties dans le dossier d'incident, énumérez le groupe de processus. Un processus peut lancer un enfant qui change de groupe, alors ne vous arrêtez pas à une seule commande. Inspectez les environnements d'exécution des conteneurs et les gestionnaires de tâches en arrière-plan auxquels votre agent peut accéder. Si l'agent dispose d'un accès SSH, vérifiez aussi les sessions actives sur chaque hôte cible.

Lorsque la tâche effectue un travail distant, utilisez l'identifiant d'opération du système distant. Par exemple, une API peut renvoyer ceci lorsqu'elle accepte une requête :

```json
{
  "operation_id": "op_4e2b7c",
  "status": "queued"
}
```

Conservez cette réponse, puis appelez le point de terminaison d'annulation documenté ou utilisez la console du service sous contrôle humain. Notez le résultat de l'annulation. Une réponse `cancel_requested` signifie que vous devez encore interroger l'opération jusqu'à ce qu'elle indique `cancelled`, `completed` ou un autre état final. N'écrivez pas « arrêté » dans les notes d'incident simplement parce que le processus local a disparu.

## Préservez les preuves avant de réinitialiser l'espace de travail

Recueillez les preuves dans un dossier d'incident séparé avant de supprimer des branches, redémarrer des services ou exécuter un script de nettoyage automatique. Vous avez besoin d'un historique chronologique qu'un autre développeur puisse examiner sans dépendre des souvenirs de l'opérateur.

Rassemblez les éléments suivants et préservez autant que possible leurs horodatages d'origine :

- La transcription de l'agent, les entrées et sorties des outils et la configuration utilisée pour l'exécution.
- Les sorties d'inspection des processus, les identifiants des processus parents et enfants, les connexions ouvertes et l'historique shell pertinent.
- Les enregistrements de session de la passerelle et les journaux d'action, y compris les refus intervenus après la révocation.
- Les événements d'audit des services distants, les identifiants d'opération, les résultats d'annulation et les identifiants des ressources modifiées.
- L'état du dépôt : commit actuel, différence, fichiers non suivis et artefacts générés.

Hachez les fichiers après leur collecte. Un manifeste simple permet aux réviseurs ultérieurs de détecter une modification accidentelle lorsque les copies passent entre l'ingénieur d'astreinte, l'équipe de sécurité et le développeur responsable du système concerné :

```sh
mkdir -p incident-run_2025_04_18/evidence
cp agent-transcript.txt incident-run_2025_04_18/evidence/
ps -o pid,ppid,pgid,lstart,command -p 48192 > incident-run_2025_04_18/evidence/process.txt
shasum -a 256 incident-run_2025_04_18/evidence/* > incident-run_2025_04_18/SHA256SUMS.txt
```

Le manifeste peut ressembler à ceci :

```text
8f7c...  incident-run_2025_04_18/evidence/agent-transcript.txt
30b1...  incident-run_2025_04_18/evidence/process.txt
```

Un hachage ne rend pas un fichier véridique. Il prouve qu'un réviseur a reçu le même fichier que celui que vous avez haché. Comparez-le avec les journaux détenus par des systèmes que l'agent ne pouvait pas modifier, comme la piste d'audit d'un fournisseur API ou un service central de journalisation en ajout seul.

Le Computer Security Incident Handling Guide de NIST, SP 800-61, considère le confinement, l'éradication, la reprise et le travail post-incident comme des activités distinctes. Cette séparation convient bien aux incidents impliquant des agents. Les équipes passent souvent directement à l'éradication en supprimant le répertoire de travail ou en faisant tourner un jeton. Elles découvrent ensuite que la transcription supprimée contenait le corps exact de la requête nécessaire pour retrouver une ressource distante.

Ne copiez pas de secrets dans le dossier d'incident sous prétexte de préserver le contexte. Capturez les identifiants des informations d'authentification, leur propriétaire, leur portée, leur date de création et leurs dernières utilisations. Ne stockez les valeurs secrètes elles-mêmes que si votre procédure d'incident l'autorise explicitement et permet de les protéger. Une archive d'incident doit réduire l'incertitude, pas créer une nouvelle fuite de secrets.

## La mort du processus parent ne prouve pas l'arrêt du travail

Supposez qu'un agent actif puisse laisser du travail derrière lui jusqu'à preuve du contraire. Les cas les plus problématiques ne sont pas les commandes shell spectaculaires, mais les actions asynchrones ordinaires qu'un développeur remarquerait à peine dans le cadre d'un travail normal.

Prenons le cas d'un agent de programmation qui envoie une demande de déploiement, lance une commande SSH démarrant une migration en arrière-plan, puis attend les tests. L'opérateur voit une cible de production inattendue et arrête l'agent parent. Le service de déploiement a déjà accepté la demande, tandis que le shell distant a lancé une commande sous `nohup`. Les deux continuent. La dernière ligne du terminal peut simplement indiquer que la connexion est fermée.

L'analyse nécessite trois vérifications distinctes :

### Inspecter le travail accepté par les API

Recherchez dans le service concerné l'identifiant d'exécution, l'identifiant de requête, l'identité du compte et la période correspondante. Déterminez si chaque requête a été refusée, mise en file, exécutée, terminée ou annulée. Pour les modifications terminées, listez les identifiants réels des ressources et comparez leur état obtenu avec l'état demandé.

Ne vous fiez pas uniquement au statut HTTP. Un `200` peut décrire une modification synchrone, un document de statut ou une réponse provenant d'un intermédiaire. Un `202` indique généralement un traitement accepté, mais la documentation du service en définit le sens final. Lisez cette documentation avant de rédiger une procédure d'annulation pour le service.

### Inspecter le travail détaché de l'agent

Sur les systèmes cibles, vérifiez les sessions du compte distant, l'arbre des processus, les tâches planifiées, les répertoires temporaires et les journaux du service. Recherchez la ligne de commande enregistrée, le répertoire de travail, l'identifiant d'exécution ou un fichier généré unique. Si une tâche distante utilise un ordonnanceur, annulez-la via cet ordonnanceur plutôt que de tuer un shell qui ne la contrôle peut-être plus.

Vérifiez aussi les rappels. Un script généré peut avoir configuré un webhook, créé un flux de travail de pull request ou déclenché la CI. Il s'agit d'acteurs distincts, avec leurs propres identifiants et calendriers. La révocation de l'agent d'origine ne les révoque pas.

C'est pourquoi une passerelle d'action limitée est plus sûre que l'accès à un shell général doté d'un environnement étendu. Vous pouvez énumérer un nombre limité de canaux et obliger chaque appel privilégié à passer par un point de contrôle. Un shell rempli d'identifiants hérités transforme chaque sous-processus en branche d'incident distincte.

## Ne faites tourner les identifiants que lorsque l'exposition le justifie

Faites tourner un identifiant lorsque vous avez des raisons de penser que l'agent, ses sous-processus, ses journaux ou son espace de travail ont pu conserver le secret. Ne le faites pas uniquement pour donner l'impression d'une réaction. Une rotation étendue perturbe les utilisateurs légitimes et peut compliquer l'analyse en modifiant les enregistrements que vous devez encore examiner.

Ces situations justifient une désactivation ou une rotation immédiate :

- L'agent a reçu un secret en clair dans une invite, une variable d'environnement, un fichier de configuration, une ligne de commande ou une sortie d'outil.
- Un identifiant est apparu dans une transcription, une différence de dépôt, un fichier temporaire ou un journal CI accessible au-delà de l'équipe chargée de l'incident.
- Vous ne pouvez pas rendre compte d'un processus enfant, d'une session distante ou d'une connexion sortante qui aurait pu lire le secret.
- L'identifiant dispose de privilèges étendus et ne possède pas de journaux fiables pour chaque utilisation.
- Le fournisseur concerné vous informe que l'identifiant a été utilisé depuis une identité ou un emplacement inexpliqué.

Si une passerelle a injecté l'identifiant et n'a renvoyé à l'agent que le résultat de l'action, la situation est très différente. L'agent a peut-être effectué une action non autorisée, mais il ne possédait pas nécessairement un secret réutilisable. Désactivez la session active et la route d'action concernée, examinez l'audit et faites tourner l'identifiant sous-jacent si l'analyse révèle un contournement de cette frontière ou un problème du côté du fournisseur.

Évitez de recommander la rotation de tous les secrets après chaque erreur d'un agent. Cette pratique est répandue parce qu'elle paraît décisive et que les identifiants divulgués ont de graves conséquences. Elle ne doit pas être la règle par défaut : elle confond utilisation non autorisée et divulgation d'un identifiant, provoque des pannes de production évitables et encourage les équipes à négliger le périmètre réel. Faites tourner rapidement les identifiants lorsque la divulgation est plausible. Dans les autres cas, conservez la possibilité de distinguer l'exécution compromise de toutes les autres.

Lorsque la rotation est nécessaire, documentez l'identifiant de l'ancien secret, l'heure de sa désactivation, les systèmes en aval qui l'utilisent, le responsable du remplacement et un test prouvant que l'ancien identifiant ne fonctionne plus. Ne placez aucune des deux valeurs dans un ticket ou une transcription. Un gestionnaire de secrets ou le mécanisme de rotation protégé du fournisseur doit gérer le remplacement.

## Le dossier d'incident doit permettre une analyse exigeante

Une analyse d'incident doit permettre à un développeur qui n'était pas d'astreinte de reconstituer la séquence sans faire confiance à un journal mutable unique. Commencez par l'intention de l'agent et l'enregistrement du processus local, puis comparez ce récit avec les enregistrements de la passerelle et les preuves des services distants.

Établissez une chronologie avec des niveaux de confiance explicites. Par exemple, « l'agent a proposé la requête » provient d'une transcription. « La passerelle a exécuté la requête » provient de l'enregistrement d'action de la passerelle. « Le fournisseur a accepté l'opération » provient de l'entrée d'audit du fournisseur. « La ressource a changé » provient de l'état final et de l'historique des modifications de la ressource. Ce sont des affirmations différentes, qui exigent des preuves différentes.

Un journal d'audit en écriture seule et chaîné par hachage offre ici une propriété utile : le composant qui exécute les actions ne peut pas réécrire silencieusement son propre historique après coup. La vérification sur texte chiffré permet aussi à un réviseur de contrôler la continuité sans obtenir l'accès à chaque secret ou charge utile d'action. Cela ne rend pas le journal complet. Il n'enregistre que les activités passées par la passerelle, raison pour laquelle les journaux des services distants restent indispensables.

Sallyport enregistre les sessions des agents et les actions individuelles dans un journal d'audit chiffré et chaîné par hachage. `sp audit verify` vérifie la chaîne hors ligne sans clé de coffre. L'analyste chargé de l'incident dispose ainsi d'un test simple à exécuter sur une copie exportée du journal :

```sh
sp audit verify /path/to/exported-audit-log
```

Une vérification réussie établit la continuité de l'enregistrement chiffré reçu. Une vérification échouée doit interrompre le nettoyage courant et déclencher la gestion des preuves, car vous devez déterminer si la rupture provient d'un dommage lors de l'export, d'une corruption du stockage ou d'une modification volontaire.

L'analyse doit produire des réponses, pas une liste vague d'observations. Identifiez l'instruction ou l'entrée déclenchante, l'autorité accordée à l'exécution, chaque action externe confirmée, chaque action qui reste incertaine, les identifiants qui ont pu s'échapper et la modification de contrôle qui aurait pu arrêter l'événement plus tôt. Si l'équipe ne peut pas nommer le premier contrôle qui a échoué, elle ajoutera probablement une demande d'approbation bruyante au lieu de corriger la route exposée.

## Reprenez le développement avec une nouvelle frontière, pas avec une session rouverte

Les développeurs peuvent reprendre leur travail après le confinement, mais ils ne doivent pas utiliser le même processus, le même état d'espace de travail ni la même autorisation. L'exécution interrompue peut conserver en mémoire des instructions non examinées, un contexte obsolète, des scripts générés ou un processus enfant que la première intervention n'a pas détecté.

Créez une nouvelle exécution avec une nouvelle identité de session. Examinez les différences du dépôt et les fichiers générés avant d'exposer la nouvelle exécution à des identifiants ou à des cibles de production. Si la tâche précédente doit continuer, fournissez à la nouvelle exécution une transmission écrite et concise indiquant quelles actions distantes sont terminées, lesquelles restent annulées et quelles ressources doivent être inspectées.

Utilisez un ensemble de permissions plus restreint pour la tâche reprise. Une tâche de revue de code a rarement besoin d'une autorité de déploiement. Une tâche qui doit interroger la production n'a généralement pas besoin d'un accès en écriture. Il ne s'agit pas d'imposer à chaque développeur un langage de politiques complexe, mais de ne pas reporter une autorisation étendue d'hier dans une exécution qui commence après un incident.

L'autorisation par session est particulièrement utile lorsqu'un nouveau processus local démarre après un arrêt, car elle oblige un humain à reconnaître qu'il s'agit d'une exécution différente. L'approbation par appel convient aux actions pour lesquelles le coût d'une écriture erronée est suffisamment élevé pour justifier une interruption. Si une carte d'approbation n'identifie pas le processus appelant et l'action précise, corrigez ce point avant de lui faire confiance pendant un incident.

Le premier exercice ne devrait prendre que quinze minutes : lancez une tâche d'agent sans danger, révoquez sa session pendant un appel API, préservez les enregistrements locaux et distants, puis confirmez que la tâche ne peut pas reprendre avec son ancienne autorité. Effectuez l'exercice sur une cible jetable. Vous repérerez ainsi les identifiants de requête manquants, les processus enfants détachés et les problèmes d'accès aux journaux lorsque le coût est faible, plutôt que pendant une véritable erreur de production.

## Faites de la révocation une action opérateur ordinaire

Une équipe qui considère la révocation comme une urgence rare hésitera lorsqu'un agent se comportera bizarrement. Les contrôles doivent rendre la décision sûre et rapide : verrouiller la frontière d'action, révoquer la session, examiner ce qui l'a déjà franchie et conserver une trace qui survivra au nettoyage.

Le choix de conception le plus solide repose sur une séparation simple. Les agents peuvent planifier et demander des actions. Un point de contrôle local détient les identifiants, identifie le processus qui fait la demande, enregistre la requête et peut refuser ce processus sans lui remettre le secret. Lorsque l'opérateur appuie sur le bouton d'arrêt, l'appel privilégié suivant doit échouer et les appels précédents doivent rester consultables.

Testez cette promesse avec les outils réellement utilisés par vos agents. Si l'équipe ne peut pas arrêter une seule exécution active sans faire tourner un identifiant partagé, ne peut pas relier une opération distante à cette exécution ou ne peut pas vérifier son historique d'actions après coup, le processus de gestion des incidents n'est pas terminé.
