7 min de lecture

Comment les gestionnaires de cookies d’agent conservent des sessions que vous n’aviez pas prévues

Les gestionnaires de cookies d’agent peuvent conserver silencieusement des sessions HTTP. Découvrez comment tester la persistance de Set-Cookie, les redirections, les changements d’identifiants et les limites d’exécution.

Comment les gestionnaires de cookies d’agent conservent des sessions que vous n’aviez pas prévues

Les clients HTTP donnent l’impression que les cookies sont inoffensifs, car les navigateurs nous ont habitués à eux. Un agent autonome en change les conséquences. Une réponse contenant Set-Cookie peut donner à la requête suivante une autorité que l’agent n’a jamais demandée, jamais affichée et qu’il peut conserver après le changement de son identifiant d’origine.

Considérez un gestionnaire de cookies comme un stockage d’authentification, pas comme un détail de transport. Si une API exige des sessions par cookie, donnez au gestionnaire un propriétaire nommé, une courte durée de vie et une limite observable. Sinon, désactivez-le. J’ai vu trop d’enquêtes sur incident commencer par quelqu’un qui affirmait que la requête n’avait pas d’identifiant, alors que le client en envoyait discrètement un dans l’en-tête Cookie.

Un serveur envoie Set-Cookie dans une réponse. Un client qui possède un gestionnaire peut renvoyer cette valeur plus tard dans un en-tête Cookie. Lorsque cette valeur identifie une session côté serveur, c’est concrètement un identifiant. Le fait qu’elle soit arrivée après une requête authentifiée ne la rend pas moins capable d’autoriser la suivante.

Les équipes se font piéger parce qu’elles se concentrent sur le secret fourni délibérément : un jeton bearer, un mot de passe basic-auth ou une requête signée. Elles vérifient d’où vient ce secret et s’il atteint l’agent. Puis une bibliothèque HTTP accepte un cookie de session sans aucune ligne explicite de code applicatif. La requête suivante peut fonctionner après la disparition de l’en-tête Authorization d’origine.

La distinction importante est celle entre l’injection d’identifiants et la poursuite d’une session. L’injection attache un secret connu à une requête. La poursuite de session laisse le serveur émettre un nouveau secret et demande au client de le renvoyer plus tard. Les deux peuvent autoriser une action. Un seul apparaît généralement dans les arguments d’appel d’un outil.

La RFC 6265 décrit cet échange comme une gestion d’état : l’agent utilisateur stocke les informations de cookie reçues dans Set-Cookie et renvoie les cookies applicables dans Cookie. Cette formulation est volontairement large, car les navigateurs web en ont besoin. Un client d’agent ne devrait pas hériter de l’habitude des navigateurs de conserver un état simplement parce que le protocole HTTP le permet.

Un cookie modifie aussi le sens d’un échec de rotation de jeton. Supposons qu’un agent appelle une API avec un jeton, reçoive sid=..., puis perde l’accès à ce jeton. Si l’API accepte le cookie de session seul, l’agent conserve un chemin vers le compte. La rotation a corrigé l’identifiant connu, mais n’a pas mis fin à la session émise. C’est à la fois une question de gestion des sessions côté serveur et de confinement côté client. Il faut traiter les deux.

Le client décide si un état caché existe

Set-Cookie ne fait rien par lui-même. Un client doit choisir de le conserver. Ce choix peut se cacher à de nombreux endroits étonnants : un client HTTP réutilisable, le gestionnaire de cookies d’une bibliothèque, un wrapper autour de fetch, un harnais de test ou une implémentation de redirection.

Certains clients courants ne conservent pas les cookies à moins de leur fournir un gestionnaire. D’autres les conservent lorsque le code attache un gestionnaire de cookies standard. Un client partagé peut alors rendre le gestionnaire partagé par accident. Ne déduisez pas le comportement de la documentation de l’API ni du fait qu’un appel a réussi. Inspectez la construction du client et lancez une sonde.

Un test propre utilise un serveur que vous contrôlez ou un point de terminaison de test inoffensif. La première réponse doit définir un cookie au nom explicite, et la seconde requête doit signaler les en-têtes qu’elle a reçus. Le résultat doit répondre à deux questions distinctes :

  1. Le client a-t-il conservé le cookie après avoir reçu Set-Cookie ?
  2. Le client a-t-il envoyé ce cookie lors d’une requête ultérieure admissible ?

Avec curl, un fichier de cookies explicite rend l’état visible :

curl -i -c /tmp/agent-cookie-test.txt https://test.example/session/start
HTTP/1.1 200 OK
Set-Cookie: agent_probe=run-7f3; Path=/; Secure; HttpOnly

curl -i -b /tmp/agent-cookie-test.txt https://test.example/session/echo
HTTP/1.1 200 OK

{"received_cookie":"agent_probe=run-7f3"}

Le fichier est l’objet de l’exercice. La première commande ne peut pas créer de session cachée à moins qu’un élément conserve sa réponse. La seconde ne peut pas en renvoyer une à moins de recevoir le fichier. Si vos outils d’agent donnent à l’équivalent de ce fichier un emplacement global de processus sans nom, vous avez créé une limite de session que personne ne peut examiner raisonnablement lors d’une revue.

Répétez la sonde en suivant exactement le chemin d’exécution de votre agent, y compris son wrapper de requêtes et ses paramètres de redirection. Un test curl direct prouve le comportement de curl, pas celui de votre outil. Notez si le gestionnaire commence vide, où il vit et ce qui l’efface.

Réutiliser entre les appels diffère de réutiliser entre les exécutions

Quelques appels dans une même tâche peuvent avoir besoin de partager une session. Réutiliser cette session dans une tâche ultérieure est une décision distincte. Confondre ces deux durées de vie transforme une petite commodité en autorité persistante.

Utilisez trois limites pour évaluer le comportement. Demandez d’abord si une requête unique a besoin de cookies. Demandez ensuite si les appels liés dans un même processus d’agent en ont besoin. Demandez enfin si un processus neuf, une tâche reprise, un autre identifiant ou une autre personne doit un jour les hériter. Chaque réponse positive doit avoir une raison explicite.

Un gestionnaire en mémoire qui disparaît avec le processus est plus facile à contenir qu’un fichier dans un répertoire de projet. Un fichier peut survivre à un plantage, une nouvelle tentative, un espace de travail copié ou un changement de la personne qui exécute la tâche. Il peut aussi se retrouver dans une archive de support ou dans la sortie d’état du contrôle de source. HttpOnly ne protège pas un fichier de cookies contre le client qui l’a écrit. Il limite seulement l’accès depuis un script de navigateur.

Je préfère un gestionnaire neuf pour chaque exécution d’agent, même lorsque le même modèle reçoit une invite de suivi. La continuité conversationnelle du modèle ne justifie pas de conserver une autorité HTTP. Si le suivi a réellement besoin de la session, demandez à l’opérateur d’approuver une poursuite sous la même limite nommée, au lieu de laisser silencieusement la dernière exécution derrière elle une session utilisable.

Les appels concurrents exigent aussi leur propre décision. Un gestionnaire partagé peut produire un comportement dépendant de l’ordre : la requête A reçoit un cookie, la requête B démarre quelques instants plus tard, et B obtient une session qu’elle n’a jamais établie. Cela rend la reproduction pénible. Donnez aux tâches concurrentes des gestionnaires distincts, sauf si l’API exige une session coordonnée et que la tâche en est explicitement propriétaire.

Les attributs de cookie limitent leur envoi, mais ne rendent pas une session inoffensive. Lisez-les comme des instructions de routage du serveur au client, puis décidez si votre client doit les respecter.

Un cookie limité à l’hôte revient à l’hôte exact qui l’a émis. Un cookie avec Domain=example.com peut revenir à des sous-domaines admissibles comme api.example.com et admin.example.com. La RFC 6265 indique aussi qu’un agent utilisateur rejette une valeur Domain qui ne correspond pas au domaine de l’hôte d’origine, mais cela ne résout pas l’erreur courante qui consiste à faire confiance à chaque sous-domaine d’un vaste domaine d’entreprise.

Path=/billing limite le cookie aux requêtes dont le chemin correspond à celui du cookie. Cela n’empêche pas un serveur situé sur un autre chemin autorisé d’accepter le même cookie s’il le reçoit par une autre route, et ne remplace pas les contrôles d’autorisation. N’utilisez pas Path comme limite de sécurité dans les discussions de conception. C’est une règle d’envoi côté client.

Secure demande au client d’envoyer le cookie uniquement par transport sécurisé. HttpOnly demande à un navigateur de ne pas l’exposer par ses API de script. Ces deux attributs relèvent d’une bonne hygiène, mais aucun ne limite la conservation, le partage entre tâches, les redirections ou la capacité de l’agent à utiliser le cookie. SameSite régit surtout le contexte de site dans un navigateur. Un agent qui n’est pas un navigateur ne doit pas y voir la preuve qu’un comportement entre sites est sûr.

Une autre erreur est facile à commettre : enregistrer les en-têtes bruts pendant le débogage. Un filtre qui supprime Authorization mais laisse Cookie n’a pas masqué l’authentification. Enregistrez la présence d’un cookie, son nom, les valeurs Domain et Path déclarées, son type d’expiration et un identifiant de corrélation irréversible si vous en avez besoin. N’enregistrez pas sa valeur.

Les redirections font du test des cookies un test de destination

Révoquez l’exécution concernée
Sessions journal enregistre l’exécution d’agent qui a effectué les appels HTTP et vous permet de la révoquer instantanément.

Une redirection n’est pas seulement une URL différente. Elle peut changer le serveur qui voit la requête suivante, le maintien des identifiants et la réponse qui peut définir un état. Testez-la comme un flux à part entière.

Commencez avec un point de terminaison qui renvoie une redirection après avoir défini un cookie. Testez ensuite chaque destination séparément : le même hôte, un sous-domaine autorisé, un sous-domaine voisin et un hôte sans rapport. Surveillez à la fois le Cookie sortant et l’Authorization sortant. Les piles HTTP font des choix différents, et un wrapper peut remplacer les valeurs par défaut.

Un bon fixture produit une courte trace comme celle-ci :

request 1  GET https://api.example.test/start
response 1  302 Location: https://api.example.test/next
            Set-Cookie: probe=A; Path=/; Secure
request 2  GET https://api.example.test/next
            Cookie: probe=A
response 2  200

Modifiez ensuite uniquement l’hôte dans Location. Si api.example.test redirige vers reports.example.test, un cookie limité à l’hôte ne doit pas suivre. Un cookie à portée Domain pourrait le faire. Votre test doit préciser le résultat attendu avant de s’exécuter, car une trace qui vous surprend est précisément ce qui compte, pas un désagrément à dissimuler.

Refusez les redirections qui changent d’origine lorsque le contrat de l’API ne les exige pas. Si vous devez les suivre, comparez les anciennes et nouvelles origines, retirez les identifiants de requête selon une règle explicite et laissez une réponse neuve établir tout nouvel état de cookie. N’utilisez jamais une politique de redirection automatique générale en supposant que la portée des cookies vous protégera.

Un test de session doit traverser les identifiants et les processus

Le test qui détecte le bogue coûteux n’est pas « requête une, requête deux ». Il franchit les limites que votre modèle d’exploitation prétend imposer.

Créez un point de terminaison inoffensif qui émet un cookie seulement après avoir reçu l’étiquette d’identifiant choisie. Faites-lui renvoyer l’étiquette de session sur chaque requête autorisée. Exécutez ensuite cette séquence :

  1. Démarrez l’exécution A avec l’identifiant A et recevez sid=A.
  2. Effectuez un second appel sans l’identifiant A, mais avec le même gestionnaire.
  3. Démarrez l’exécution B avec l’identifiant B et un gestionnaire vide.
  4. Démarrez l’exécution C sans identifiant et avec tout gestionnaire persistant provenant de l’exécution A.
  5. Révoquez l’identifiant A ou invalidez sa session sur le serveur de test, puis réessayez avec le gestionnaire de l’exécution A.

La sortie attendue relève d’un choix de politique, pas d’une réponse universelle. Une API fondée sur les cookies peut autoriser volontairement le second appel dans l’exécution A. L’exécution B ne doit pas voir l’état de A. L’exécution C doit échouer, sauf si vous avez explicitement approuvé la persistance. Après révocation, le serveur de test doit refuser l’ancienne session si votre modèle de menace exige que la rotation de jeton supprime l’accès actif.

Écrivez l’attente à côté du test au lieu de l’enfouir dans la mémoire d’un développeur. Un tableau concis dans un commentaire de test suffit :

run A, same jar, no bearer header: allowed only if session continuation is intended
run B, fresh jar, credential B: must identify as B
run C, persisted jar, no credential: rejected
run A after session invalidation: rejected

Cela révèle une distinction que les équipes brouillent souvent : révoquer un identifiant d’amorçage et révoquer les sessions émises ne sont pas la même opération. Le propriétaire de l’API doit invalider les sessions. Le propriétaire de l’outil d’agent doit éviter de les conserver au-delà de leur durée de vie approuvée. Aucune des deux parties ne peut supposer que l’autre s’en est chargée.

Désactivez les gestionnaires implicites sauf si l’API en exige un

Tracez chaque action HTTP
Activity journal conserve chaque action HTTP exécutée, au lieu de laisser l’utilisation des identifiants dans le contexte de l’agent.

Le choix raisonnable par défaut pour une action HTTP d’agent est l’absence de stockage de cookies et d’en-tête Cookie automatique. Une réponse peut tout de même contenir Set-Cookie. Notez que cela s’est produit si votre conception d’audit le permet, puis éliminez-le. L’API doit utiliser son identifiant de requête habituel lors de l’appel suivant.

Cette recommandation est impopulaire, car de nombreuses API proches du web ne fonctionnent après un point de terminaison de connexion que si le client conserve un cookie. Les gens choisissent un gestionnaire partagé parce qu’il fait passer les démonstrations et les tests d’intégration. C’est la mauvaise solution lorsque l’API documentée prend en charge les jetons bearer ou un autre mécanisme limité à la requête. Vous conservez une autorité invisible pour compenser un chemin d’intégration que vous n’auriez pas dû choisir.

Si l’API exige réellement des cookies, faites du gestionnaire une capacité explicite. L’appelant doit sélectionner un gestionnaire vide et nommé au début de l’exécution, l’outil doit signaler quand la réponse crée ou remplace un cookie, et le gestionnaire doit disparaître à la fin. Ne laissez pas un point de terminaison inscrire chaque agent dans une session durable simplement en renvoyant un en-tête.

Une politique minimale peut être assez simple pour être revue :

cookie mode: disabled by default
allowed mode: ephemeral per agent run
persistence: prohibited
sharing: prohibited between agent processes
redirects: same-origin only unless the action definition permits another origin
logging: record cookie names and scope, never values

C’est volontairement moins ingénieux qu’un moteur de règles. Une politique de cookies sophistiquée accumule les exceptions jusqu’à ce que plus personne ne puisse dire quelle action transporte quel état. Un petit ensemble de choix donne aux réviseurs une réponse réelle.

Auditez la transition d’état, pas seulement la requête

Une piste d’audit qui liste les URL et les codes d’état manquera l’événement le plus utile : une réponse a changé ce que les appels ultérieurs peuvent faire. Enregistrez les changements d’état des cookies comme des événements à part entière, sans conserver le secret de session lui-même.

Pour chaque action HTTP, l’enregistrement doit permettre de répondre à ces questions : la requête a-t-elle envoyé des cookies, la réponse en a-t-elle défini ou effacé, quel gestionnaire les a reçus, ce gestionnaire appartenait-il à cette exécution et une redirection a-t-elle eu lieu ? Les noms et attributs des cookies suffisent généralement au diagnostic. Ne stockez les valeurs que si vous avez une conception de sécurité convaincante pour les protéger et les faire expirer, ce dont la plupart des outils d’agent n’ont pas besoin.

Lorsqu’un agent utilise Sallyport pour des actions HTTP, le coffre peut garder l’identifiant API configuré hors de l’agent pendant l’exécution de l’action. Cette séparation n’est utile que si le client HTTP traite avec la même méfiance tout état de session renvoyé, plutôt que de le transformer discrètement en un autre chemin d’identifiant.

Les enregistrements d’audit ont aussi besoin d’une limite d’exécution lisible par un humain. Si un opérateur révoque une exécution d’agent, il doit savoir si cet acte empêche les futurs appels uniquement via l’identifiant configuré ou s’il efface aussi l’état de session rattaché à l’exécution. Si ce n’est pas le cas, dites-le clairement et rendez l’état restant inaccessible à un processus ultérieur.

Le premier test que j’ajouterais est volontairement banal : un point de terminaison envoie Set-Cookie, le suivant confirme s’il est arrivé, puis un nouveau processus d’agent répète l’appel. Exécutez-le avant d’ajouter les nouvelles tentatives, les redirections, la compatibilité navigateur ou un cache persistant. Si la réponse n’est pas évidente dans la trace, votre client possède plus d’autorité que son interface ne l’admet.

Les auteurs d’API peuvent rendre les agents plus sûrs sans deviner

Vérifiez la trace des actions
Son journal d’audit chiffré et chaîné par hachage peut être vérifié hors ligne sur le texte chiffré, sans clé du coffre.

Les auteurs d’API devraient documenter si les cookies sont nécessaires, ce qui les crée, leur durée de vie prévue et la manière dont les clients les invalident. Une phrase disant « utilisez ce point de terminaison après la connexion » ne suffit pas lorsqu’une connexion peut émettre une session qui survit à l’identifiant utilisé pour l’obtenir.

Proposez une solution limitée à la requête lorsque c’est possible. L’authentification bearer, les requêtes signées ou un jeton d’action à portée étroite rendent souvent le comportement du client plus facile à auditer, car chaque appel porte ouvertement son autorité. Ces mécanismes ne sont pas automatiquement sûrs pour autant, mais ils évitent un canal de renvoi supplémentaire caché dans la mémoire du client.

Si vous émettez un cookie de session, faites fonctionner l’invalidation de session et testez-la. Une rotation de jeton sans invalidation de session donne aux opérateurs une fausse impression de résolution, qui peut être très désagréable. Si vous acceptez à la fois un jeton bearer et un cookie de session, définissez lequel l’emporte en cas de désaccord et exposez ce choix dans la sortie de diagnostic.

Ne dites pas aux créateurs d’agents d’imiter les navigateurs, sauf si votre service dépend réellement de leur comportement. Les agents effectuent des appels répétés sans surveillance et opèrent souvent dans des tâches distinctes. L’état pratique et durable d’un navigateur est un mauvais choix par défaut dans cet environnement.

Le choix sûr par défaut est un client neuf sans session mémorisée

La prise en charge des cookies n’est pas mauvaise. L’état sans propriétaire l’est. Un gestionnaire explicitement choisi et de courte durée peut être la bonne manière de terminer une tâche API à plusieurs appels. Un gestionnaire qui apparaît parce que quelqu’un a réutilisé un client HTTP est un accident qui attend la bonne nouvelle tentative, redirection ou rotation d’identifiant.

Rendez la limite de session visible dans l’interface de l’outil et dans l’enregistrement d’audit. Puis prouvez-la avec le test entre exécutions. La trace de requête doit permettre à un réviseur d’indiquer chaque chemin d’identifiant dont disposait l’agent, y compris ceux que le serveur a tenté de lui redonner.

FAQ

Qu’est-ce qu’un gestionnaire de cookies dans un client HTTP ?

Un gestionnaire de cookies est le stockage côté client qui mémorise les cookies reçus dans les réponses HTTP et décide quelles requêtes ultérieures doivent les renvoyer. Dans un outil d’agent, cette mémoire peut transformer des appels distincts en une même session authentifiée, semblable à celle d’un navigateur.

Un agent d’IA doit-il conserver les cookies entre les appels API ?

Cela peut être approprié si l’API utilise les cookies comme mécanisme de session prévu et que l’exécution a besoin de plusieurs appels liés. C’est un mauvais choix par défaut lorsque l’agent dispose de jetons bearer, de requêtes signées ou de limites de tâche distinctes, car le cookie crée une autorité difficile à voir dans l’invite.

Un cookie de session peut-il survivre à la rotation des identifiants ?

Un cookie peut survivre à l’identifiant qui a conduit le serveur à l’émettre. Si le serveur accepte le cookie de session sans revérifier le jeton bearer, supprimer ou faire tourner ce jeton ne met pas fin à la session déjà émise.

Les clients HTTP stockent-ils automatiquement les en-têtes Set-Cookie ?

Ne le supposez pas. Testez-le avec un point de terminaison qui enregistre l’en-tête Cookie entrant, car les clients diffèrent : certains ne conservent les cookies qu’avec un gestionnaire explicite, tandis que d’autres ajoutent un stockage de cookies via un client partagé, un wrapper ou un gestionnaire de redirection.

Combien de temps une session de cookies d’agent doit-elle durer ?

La limite la plus sûre est un gestionnaire de cookies neuf par processus d’agent ou par tâche explicitement définie. Effacez-le à la fin, ne l’écrivez pas dans un espace de travail réutilisable et exigez une décision délibérée avant de le partager avec une autre exécution.

Que signifient Domain et Path sur un cookie HTTP ?

Un cookie limité à l’hôte revient uniquement à l’hôte qui l’a défini, tandis qu’un attribut Domain peut le rendre disponible aux sous-domaines. L’attribut Path limite les endroits où le client l’envoie, mais c’est une règle de routage, pas une limite de contrôle d’accès.

L’attribut de cookie Secure rend-il les sessions d’agent sûres ?

Non. Secure signifie que le client ne doit envoyer le cookie que sur HTTPS. Cet attribut ne dit rien sur le fait qu’un agent doit le conserver, le partager ou le traiter comme un substitut à un autre identifiant.

Les redirections peuvent-elles provoquer une fuite de cookies ?

Les redirections peuvent amener un client vers un hôte qui définit un cookie, ou vers un hôte qui en reçoit un, selon le gestionnaire et la portée du cookie. Testez les redirections séparément et refusez celles qui changent d’origine lorsque l’API n’en a pas besoin.

Que faut-il enregistrer sur les cookies sans divulguer de secrets ?

Enregistrez la destination de la requête, le fait que des cookies ont été envoyés ou reçus, leurs noms, leur portée et l’identité du gestionnaire ou la limite de l’exécution. Évitez d’enregistrer les valeurs des cookies, car elles constituent souvent l’identifiant de session.

Comment empêcher les sessions cachées dans les outils HTTP d’agent ?

Gardez l’injection habituelle d’identifiants et le gestionnaire de cookies séparés, à la fois dans le code et lors de la revue. Donnez au gestionnaire une courte durée de vie, explicitez sa règle de partage et effacez-le à la fin de l’exécution. Le traiter comme une simple commodité HTTP masque une décision d’authentification.

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