Des articles approfondis sur les technologies qui façonnent l'avenir.

Votre client API est un coffre-fort : auditez-le

Votre client API est un coffre-fort. Apprenez à auditer vos outils de dev : installations silencieuses, télémétrie et flux de données sortants.

Un coffre-fort posé sur le clavier d'un ordinateur portable, avec des câbles lumineux reliés à des appareils voisins.
Votre client API détient les clés, et certains outils vont bien au-delà de leurs propres limites.

Un développeur ouvre un client HTTP sur son Mac. Rien d'autre. Aucun clic, aucune boîte de dialogue de consentement, aucune case « activer les fonctionnalités IA ». Le lendemain, son agent de code n'arrive plus à s'authentifier auprès d'un serveur MCP distant qu'il n'a jamais configuré, achemine les appels API via des skills qu'il n'a jamais installés et embarque un hook de démarrage cryptographiquement approuvé qu'il n'a jamais validé. Ce n'est pas une hypothèse : c'est ce que montrent les preuves d'un rapport de bug récent et minutieusement documenté sur l'application de bureau de Postman. Elle installe automatiquement des plugins dans Codex et Claude Code, écrit dans les configurations globales des agents et tente de marquer son propre hook de session comme fiable. Si la sécurité de votre client API vous importe, c'est cet incident qui devrait changer la façon dont vous traitez chaque outil de dev de bureau installé sur votre machine.

Ce que l'application de bureau Postman a réellement fait

Laissez de côté l'indignation et regardez les faits, car le rédacteur du rapport a fait le travail que la plupart d'entre nous ne font jamais. Le fichier de log de Postman a enregistré un événement auto-existing-upgrade : sur une installation de bureau existante, avec un compte connecté, un script s'est exécuté et a signalé claude-code:installed,codex:installed. Aucune question posée. La configuration Codex globale de l'utilisateur a gagné une nouvelle marketplace pointant vers un dépôt git de Postman, un plugin activé et un enregistrement de confiance pour un hook. Les paramètres de Claude Code ont gagné un plugin activé et des enregistrements d'installation dont les horodatages correspondent à la même fenêtre. Un binaire CLI de Postman est apparu dans ~/.local/bin. Et une connexion MCP distante a été pointée vers les serveurs de Postman, connexion qui a ensuite échoué à l'authentification et généré une avalanche d'erreurs. C'est la seule raison pour laquelle l'utilisateur a remarqué quoi que ce soit.

Deux détails méritent d'être relus. D'abord, le hook de démarrage de session installé demande à l'agent que, avant de répondre à toute tâche d'ingénierie API non triviale (conception, tests, mocks, documentation, déploiement), il charge le skill de Postman. Ce n'est pas une intégration sur demande : c'est une application qui réécrit le comportement par défaut de l'application d'un autre éditeur. Ensuite, le code de l'installeur récupère explicitement le hash du hook et l'insère dans l'état de confiance des hooks de l'agent. Le mécanisme de confiance existe pour que l'utilisateur approuve les hooks. Laisser l'installeur approuver son propre hook revient à signer soi-même son autorisation.

Le rédacteur a été prudent : il précise explicitement que l'enregistrement de confiance ne prouve pas à lui seul qui l'a créé, et il ne formule aucune accusation d'exfiltration. Cette retenue rend le rapport plus crédible, pas moins. Ce qu'il prouve suffit : une modification silencieuse d'outils sans rapport, une instruction comportementale large injectée au démarrage de la session d'un agent, et une tentative de contournement d'un contrôle de consentement de l'utilisateur. Dans toute revue de sécurité que j'ai menée, cette combinaison suffit à retirer un produit de la flotte en attendant une enquête.

Pourquoi votre client API est un coffre-fort de identifiants

Voici la partie que les équipes sous-estiment systématiquement. Un client API n'est pas un éditeur de texte avec un bouton d'envoi. C'est là que vivent vos bearer tokens, cookies de session, certificats clients mTLS, secrets clients OAuth et en-têtes de requêtes signées. Les variables d'environnement contenant des URL de bases de données et des clés tierces y sont collées. Si vous utilisez une syntaxe de templating comme {{api_secret}}, la valeur résolue transite par l'application à chaque requête et, selon la conception de la télémétrie de l'éditeur, potentiellement par son pipeline de journalisation également. Un praticien qui enquêtait sur la conformité HIPAA a rapporté avoir trouvé exactement cela : des valeurs de secrets résolues dans le trafic de journalisation sortant, l'application se dégradant lorsque ce point de terminaison était bloqué. Je ne peux pas vérifier chaque détail de manière indépendante, mais cela correspond au schéma architectural que j'ai vu dans d'autres outils de bureau « pratiques » : une journalisation complète des requêtes livrée comme fonctionnalité.

Ajoutez maintenant l'angle des agents. Quand un outil installe un plugin dans votre agent de code et enregistre un hook de session, il fait entrer ses instructions dans le contexte d'un processus capable de lire votre base de code, d'exécuter des commandes shell et de détenir son propre jeu d'identifiants. Le rayon d'impact ne se limite plus à « mes collections API fuient » : c'est « chaque secret accessible depuis l'environnement de mon agent n'est qu'à un mauvais prompt ou à un skill compromis d'un mauvais point de terminaison ». Nous avons déjà écrit sur la façon dont les outils CLI qui installent des démons en arrière-plan élargissent discrètement leur surface d'attaque ; c'est le même schéma, avec une charge utile plus intelligente. Un démon visible dans ps paraît presque poli à côté d'un hook d'instructions logé dans le magasin de confiance d'un autre éditeur.

Si vous regardez la modélisation des menaces avec honnêteté, la conclusion est inconfortable : un client API de bureau se situe à l'intersection des secrets, de l'accès réseau et, de plus en plus, des plans de contrôle des agents. Il mérite le même examen que celui que vous donneriez à un gestionnaire de mots de passe ou à un runner CI. Presque personne ne lui accorde cet examen. C'est la faille qu'exploite cet incident, et c'est pourquoi la réponse doit être procédurale, pas seulement émotionnelle.

Pourquoi les options de désactivation et les interrupteurs des éditeurs échouent

Le premier réflexe après un incident de ce type est de fouiller dans les préférences de l'application à la recherche d'un interrupteur de télémétrie, de le désactiver et de passer à autre chose. J'ai vu des équipes entières faire cela et appeler ça une remédiation. C'est du théâtre, pour trois raisons.

  • Le consentement peut dépendre de la version. L'installation de Postman a été déclenchée par un feature flag sur un compte existant et connecté. L'interrupteur qui existe aujourd'hui ne vous dit pas quels flags seront livrés demain, et les mises à jour automatiques font arriver demain sans rien demander.
  • Les interrupteurs couvrent ce qui est documenté, pas ce qui est possible. Un réglage de confidentialité contrôle les chemins de code que l'éditeur a choisi d'exposer. L'installeur de plugins n'était pas une préférence documentée : c'était un chemin de mise à niveau scripté. On ne peut pas désactiver une option qu'on ne voit pas.
  • Les décisions de confiance se prennent en dehors de l'application. La tentative d'approbation du hook s'est produite dans la configuration de Codex, pas dans celle de Postman. Même un panneau de réglages parfaitement honnête dans l'application source n'aurait pas fait remonter cela.

L'échec profond est structurel : les options de désactivation font reposer la vigilance sur la partie la moins informée. L'éditeur sait ce que l'updater peut faire ; vous, non. L'éditeur sait vers quels points de terminaison l'application appelle son serveur ; vous, vous devinez. Tout contrôle qui exige que la partie la moins informée se documente en continu plus vite que la partie la mieux informée finira par échouer. C'est aussi la raison pour laquelle les problèmes de confiance dans les marketplaces de plugins d'IDE continuent de mordre les gens : la frontière de sécurité que vous croyez gérer n'est pas celle qui est franchie.

La confiance envers l'éditeur n'est pas sans valeur, mais elle ne peut pas servir de contrôle. C'est un facteur pour décider quoi installer, pas un mécanisme pour garantir que le logiciel installé reste honnête. Une fois ce point intégré, la stratégie d'audit s'écrit d'elle-même : vérifier le comportement depuis l'extérieur, en continu, avec des outils que l'éditeur ne contrôle pas.

Pourquoi les audits de sécurité ponctuels échouent aussi

La deuxième tentative échouée est plus respectable : l'audit ponctuel. L'équipe sécurité examine l'outil, contrôle ses appels réseau, lit la politique de confidentialité, émet une approbation et classe le rapport. Terminé, jusqu'à ce que l'updater se lance. Les outils de dev de bureau sortent désormais à une cadence hebdomadaire, voire quotidienne, et les feature flags signifient que deux utilisateurs sur le même numéro de version peuvent exécuter un code sensiblement différent. Le comportement de cet incident était conditionné par un flag côté serveur et une condition « utilisateur existant ». Une installation propre, examinée par votre équipe sécurité, peut donc paraître irréprochable pendant que vos utilisateurs de longue date reçoivent le plugin.

J'ai déjà été piégé par exactement ce trou. Il y a des années, j'ai approuvé un client de synchronisation après une revue approfondie : capture de trafic propre, permissions saines, aucun mécanisme de persistance. Six mois plus tard, une mise à jour a ajouté un LaunchAgent et un écouteur de socket. Nous ne l'avons découvert que parce qu'un portable avec un VPN instable affichait sans cesse d'étranges tentatives de reconnexion dans un journal de pare-feu. Personne n'avait réexaminé quoi que ce soit, parce que rien dans le processus ne l'exigeait. L'approbation était un instantané ; le logiciel, lui, était un film.

Les deux correctifs bon marché échouent donc : faire confiance aux réglages de l'éditeur échoue parce que le comportement intéressant ne se trouve pas dans les réglages, et les audits ponctuels échouent parce que le comportement intéressant est livré après l'audit. Ce qui fonctionne, c'est de considérer l'état de votre propre machine comme la source de vérité et de surveiller ses changements. C'est moins glamour qu'une revue d'achats, mais cela capte la réalité plutôt que les intentions.

Une loupe au-dessus d'une carte électronique dont un chemin rompt une frontière.
Les audits ponctuels ne voient la carte qu'une fois ; le comportement change à chaque passage de l'updater.

Comment auditer réellement les outils de développement sur le poste

L'approche pratique repose sur trois piliers : prendre un instantané de l'état qui compte, surveiller le réseau, et contenir ce que vous ne pouvez pas vérifier totalement. Aucun de ces éléments n'exige un outillage d'entreprise. Il faut de la rigueur et environ une heure de mise en place.

Détecter les installations silencieuses de plugins avec des instantanés de configuration

Chaque agent de code et chaque outil de dev de votre machine dispose d'un petit ensemble de fichiers qui définissent son comportement : ~/.codex/config.toml, ~/.claude/settings.json et le répertoire des plugins, les configurations MCP, les fichiers rc du shell, ~/Library/LaunchAgents, ~/.local/bin. Ces fichiers constituent la frontière du consentement. Tout ce qui les modifie sans demander est précisément ce que vous cherchez à détecter. Calculez donc leur hash chaque jour et comparez-les :

#!/usr/bin/env bash
# snapshot-agent-configs.sh — hash every file your agents and shells read,
# then diff against yesterday. Run from cron or launchd.
set -euo pipefail
SNAP_DIR="$HOME/.config-audit"
mkdir -p "$SNAP_DIR"
TODAY="$SNAP_DIR/$(date +%F).txt"
find \
"$HOME/.codex" \
"$HOME/.claude" \
"$HOME/.config" \
"$HOME/.local/bin" \
"$HOME/Library/LaunchAgents" \
-type f 2>/dev/null \
| sort \
| xargs shasum -a 256 > "$TODAY"
PREV=$(ls -t "$SNAP_DIR"/*.txt 2>/dev/null | sed -n '2p' || true)
if [ -n "${PREV:-}" ]; then
if ! diff -u "$PREV" "$TODAY" > "$SNAP_DIR/latest.diff"; then
echo "config drift detected — see $SNAP_DIR/latest.diff" \
| mail -s "agent config drift" you@example.com || \
cat "$SNAP_DIR/latest.diff"
fi
fi

C'est rudimentaire, et c'est très bien ainsi. Si ce script avait tourné sur la machine du rédacteur, la modification du config.toml de Codex, les nouveaux enregistrements de plugins Claude et le binaire CLI dans ~/.local/bin seraient tous apparus dans un seul diff le lendemain matin. Le rapport signal/bruit est excellent, car ces répertoires sont par ailleurs silencieux : vos propres modifications sont les seuls changements légitimes, et vous savez quand vous les avez faites. Associez-le à la sortie de launchctl list | grep -v com.apple dans le même instantané, et vous détecterez aussi les mécanismes de persistance le jour même de leur apparition.

Surveiller les flux sortants, pas seulement les fichiers

L'intégrité des fichiers vous dit ce qui a changé sur le disque ; elle ne vous dit pas ce qui a quitté la machine. Pour les flux sortants, il vous faut une visibilité par application. Sur macOS, Little Snitch ou le pare-feu open source LuLu vous alerteront sur toute nouvelle connexion sortante par processus : la première fois que l'updater de Postman ou un nouveau binaire CLI contacte un hôte inconnu, vous obtenez une question au lieu d'un fait accompli. Sous Linux, opensnitch fait le même travail. Si vous voulez simplement vérifier manuellement ce que fait une application bavarde à l'instant :

# Every established outbound connection, grouped by process
sudo lsof -iTCP -sTCP:ESTABLISHED -P -n | awk '{print $1, $9}' | sort | uniq -c | sort -rn
# Watch one vendor's traffic live (find the process name first)
sudo tcpdump -i any -n host mcp.postman.com

Deux choses à chercher : les destinations sans rapport avec la fonction affichée de l'outil, et les connexions qui persistent alors que l'application est inactive. Un client HTTP devrait rester silencieux quand vous ne cliquez pas sur envoyer. Les points de terminaison de télémétrie ne sont pas automatiquement accablants, mais, comme le montre l'enquête HIPAA citée plus haut, ce qui compte, c'est la charge utile. Si votre client résout les {{secrets}} côté client et journalise le détail complet des requêtes côté serveur, « données d'usage anonymes » ne signifie rien. La seule façon de le savoir est de capturer et de lire, idéalement pendant une session où vous avez délibérément chargé un canary token, c'est-à-dire un faux identifiant unique, dans une variable d'environnement, et où vous avez observé s'il transitait là où il ne devrait pas. Les canary tokens transforment « nous pensons qu'ils pourraient » en « nous savons qu'ils l'ont fait ».

Contenir ce que vous ne pouvez pas entièrement faire confiance

La dernière étape admet que vous ne détecterez pas tout. Limitez donc le rayon d'impact. Lancez les outils gourmands en identifiants dans un compte utilisateur système dédié ou une VM légère, pour que leur portée sur le système de fichiers s'arrête à la frontière du bac à sable. macOS et Linux rendent un second utilisateur peu coûteux, et des outils comme firejail sous Linux peuvent interdire des arborescences entières par application. Gardez les vrais secrets de production hors des outils de bureau : utilisez des jetons à courte durée de vie, des comptes de service à périmètre restreint et une signature de requêtes qui expire. Si un outil exige un identifiant de production longue durée pour être utile, cette exigence est elle-même un constat. Nous avons déjà défendu l'idée que le confinement bat la surveillance lorsque le coût d'un raté est élevé : pour les agents et pour les outils qui les configurent, le confinement est la couche qui fonctionne encore le jour où votre surveillance a un angle mort.

Un playbook de retour arrière pour les incidents liés aux outils

Quand vous détectez quelque chose, supprimer l'application fautive n'est que la première étape sur une liste d'environ six. La liste de suppression du rédacteur de l'article sur Postman a la bonne forme, et il vaut la peine de l'intégrer avant d'en avoir besoin :

  1. Préserver les preuves d'abord. Copiez les logs, les configurations et les numéros de version dans un endroit sûr avant de désinstaller. Le main.log de Postman était ici l'arme fatale, et les scripts de désinstallation adorent le supprimer.
  2. Supprimer l'application et ses auxiliaires. Le bundle de l'application, plus tout ce qu'elle a déposé dans ~/.local/bin, Application Support et les caches.
  3. Nettoyer les configurations des agents. Retirez les entrées de marketplace, les blocs de plugins activés, les définitions de serveurs MCP et les répertoires de plugins en cache dans chaque hôte d'agent, pas seulement dans le plus évident.
  4. Révoquer les enregistrements de confiance. Supprimez les entrées trusted_hash de hooks que vous n'avez pas approuvés. Puis auditez les autres hooks du même fichier : si l'un a été introduit en contrebande, vérifiez le reste.
  5. Vérifier la persistance. LaunchAgents, LaunchDaemons, éléments de connexion, entrées cron, ajouts dans les fichiers rc du shell.
  6. Faire tourner les clés qui y ont transité. Tout identifiant qui a vécu dans les environnements ou les collections de l'outil doit être considéré comme exposé. La rotation est pénible ; la réponse à incident est pire.
  7. Vérifier que la suppression tient. Gardez votre script d'instantanés actif pendant quelques semaines. Une réinstallation avec un autre drapeau est un schéma connu.

Ce qui ne figure pas sur la liste : déposer un ticket et attendre. Faites-le aussi, des rapports publics et bien étayés sont la façon dont le reste d'entre nous apprend les choses, mais votre hygiène personnelle ne peut pas dépendre de la feuille de route de l'éditeur.

Une silhouette débranchant et enroulant des câbles sur un équipement serveur.
Une bonne réponse à incident est méthodique : préserver, supprimer, nettoyer, faire tourner, vérifier.

La leçon plus large sur la sécurité des outils de développement

Il est tentant de faire de cette histoire une simple affaire de trajectoire d'une seule entreprise : un outil léger et apprécié qui a levé des centaines de millions, recruté une petite armée et doit désormais justifier une valorisation de plusieurs milliards avec des connexions, des abonnements et de l'IA partout. Ce récit est satisfaisant et globalement vrai, mais il dédouane trop facilement le reste d'entre nous. La même logique d'incitation se trouve désormais sous la moitié des outils de votre machine. Chaque éditeur qui a une histoire d'IA à raconter veut son plugin dans votre agent, son serveur MCP dans votre configuration, son hook dans le démarrage de vos sessions. Certains demanderont la permission. Les faits montrent qu'au moins l'un d'eux a jugé que demander était facultatif.

La réaction du marché est déjà visible, et elle est instructive : les clients API hors ligne et natifs de git, comme Bruno, Kreya ou Yaak, connaissent un regain précisément parce que leur modèle de confiance est lisible. Des fichiers dans votre dépôt, des requêtes depuis votre machine, aucun compte requis. Quand le format de stockage d'un outil est un dossier de fichiers texte, l'auditer revient à faire un git diff. Ce n'est pas de la nostalgie, c'est une architecture de sécurité. L'incident de supply chain LiteLLM a enseigné la même leçon côté registres de paquets : les artefacts que vous pouvez inspecter et épingler sont ceux que vous pouvez défendre.

Un consentement qui vit dans un feature flag n'est pas un consentement. Si un outil peut changer ce qu'il fait sans changer de numéro de version, votre approbation de cet outil ne veut rien dire.

Voici donc la position que je défendrai : arrêtez d'évaluer les outils de dev de bureau sur leurs fonctionnalités et commencez à les évaluer sur leur réversibilité. Puis-je voir tout ce qu'ils écrivent ? Puis-je comparer leur configuration ? Puis-je les utiliser sans compte, hors ligne, derrière un pare-feu qui journalise ? Puis-je les supprimer complètement, y compris ce qu'ils ont touché en dehors de leur propre répertoire ? Les outils qui résistent à ces questions tendent à être ennuyeux, et l'ennui est exactement ce que vous voulez entre vos identifiants et le réseau. Ceux qui échouent, quelle que soit la qualité de leur autocomplétion, doivent aller dans un bac à sable ou hors de la machine. Votre client API est un coffre-fort. Traitez-le comme tel, car les éditeurs, eux, le font déjà, simplement pas de la manière que vous espérez.