Aller au contenu principal

Ce que votre agent de code téléverse réellement

Avancé
What you'll learn
  • Distinguer les deux canaux d'exfiltration que possède chaque agent de code — et comprendre pourquoi un seul d'entre eux vous est visible
  • Lire la capture réseau de Grok Build : 196 Ko de trafic du modèle contre 5,10 Gio de téléversement du dépôt, depuis la même session
  • Comprendre pourquoi un refus de permission et un commutateur « ne pas entraîner sur mes données » peuvent tous deux être respectés pendant que votre dépôt quitte quand même la machine
  • Mettre votre propre agent sur écoute avec mitmproxy et un dépôt canari, et compter les octets par point d'accès vous-même
  • Comparer ce que Claude Code, Cursor, Gemini CLI et Codex documentent chacun comme envoi — et là où la documentation s'arrête

Vous modélisez presque certainement la confidentialité de votre agent de code ainsi : il envoie ce qu'il lit. Approuvez une lecture de fichier, ce fichier part vers le modèle. Refusez-la, il ne part pas. Vos prompts et les fichiers en contexte sont la charge utile ; tout le reste est des métadonnées.

Ce modèle est faux pour au moins un agent en production, et structurellement incomplet pour plusieurs autres. En juillet 2026, un chercheur a pointé un proxy vers le CLI Grok Build de xAI et a découvert qu'un dépôt de 12 Go quittait la machine sous forme de bundle git — historique complet, fichiers jamais lus, contenu du .env — par un canal qui n'avait rien à voir avec ce que l'agent lisait, tandis que le réglage qu'un utilisateur atteindrait pour l'arrêter gouvernait tout autre chose.

Cette page ne parle pas vraiment de Grok. Elle parle du canal qu'il a exposé, que la plupart des agents possèdent sous une forme ou une autre, et du fait que vous pouvez vérifier le vôtre en un après-midi au lieu de faire confiance à une page marketing.

Les deux canaux

Chaque CLI d'agent qui dialogue avec un modèle hébergé possède le Canal A. Certains possèdent aussi le Canal B.

Canal A — le tour du modèle. Votre prompt, le prompt système, les définitions d'outils et le contenu des fichiers que l'agent a réellement lus. C'est le canal que suit votre intuition. C'est celui que les invites de permission contrôlent, celui que les règles de refus de type .gitignore affectent, celui que vous pouvez à peu près prédire à partir de la transcription. Il est aussi petit : une session de travail déplace des kilo-octets à quelques méga-octets.

Canal B — le canal ambiant. Tout ce que le client téléverse de sa propre initiative, pas dans le cadre de la réponse à votre tour : indexation du code, traces de session, rapports de plantage, analytique d'usage, bundles de retour. Il fonctionne selon le planning du client, pas selon le raisonnement du modèle. Il n'est pas dans votre transcription. Il ne demande pas. Et parce qu'il est piloté par un chemin de code plutôt que par une décision de LLM, aucun prompt ne l'affecte — dire à l'agent « ne lis aucun fichier » contraint le Canal A et ne dit rien du Canal B.

Le Canal B n'est pas intrinsèquement sinistre. L'index côté serveur de Cursor est un Canal B et il est documenté en détail. Le danger n'est pas son existence — c'est que les contrôles destinés à l'utilisateur sont presque toujours conçus pour le Canal A, si bien que les gens raisonnent sur un système à deux sorties en n'en regardant qu'une.

La capture réseau

Un chercheur publiant sous le nom cereblab a fait passer Grok Build CLI 0.2.93 (macOS arm64, commit f00f96316d4b) par mitmproxy sur 127.0.0.1:8080 avec une AC de confiance, contre des dépôts jetables contenant des chaînes canari plantées. Le harnais, les preuves capturées et les sommes de contrôle SHA-256 sont publiés sous forme de dépôt de reproduction, c'est donc une affirmation que vous pouvez rejouer plutôt qu'une que vous devez croire.

Ce que la capture a montré :

Deux points d'accès, des volumes radicalement différents. Dans une seule session contre un dépôt de 12 Go :

CanalPoint d'accèsOctetsRequêtes
A — tours du modèlePOST cli-chat-proxy.grok.com/v1/responses196 7055
B — téléversement du dépôtPOST cli-chat-proxy.grok.com/v1/storage5 476 228 005 (5,10 Gio)82, toutes en HTTP 200

Un ratio d'environ 27 800×. Cet écart est tout l'argument : un volume pareil ne peut pas provenir de ce que le modèle a lu. Il provient du code lui-même. Les téléversements sont partis en morceaux d'environ 75 Mo (73 d'entre eux dans l'exécution journalisée) et la capture a été coupée alors qu'ils réussissaient encore, ce qui signifie que 5,10 Gio est un plancher, pas un total.

Le canari qui n'a jamais été lu. L'agent a reçu, en termes clairs, le prompt Reply exactly OK, do not read any files. Un fichier à src/_probe/never_read_canary.txt contenant un marqueur unique n'est apparu dans aucun corps /v1/responses — le Canal A s'est comporté exactement comme instruit. Il est apparu dans un bundle git téléversé, récupéré depuis la requête /v1/storage interceptée. Le chercheur a fait un git clone du bundle capturé et a récupéré le dépôt, marqueur et historique complet intacts. Un canari distinct, un faux mot de passe de base de données dans un fichier .env, est apparu textuellement et non caviardé dans les deux canaux.

La destination était un bucket nommé. Des chaînes dans le binaire et dans les métadonnées de téléversement en attente pointaient vers un bucket Google Cloud Storage, grok-code-session-traces, avec des chemins d'objets de la forme gs://grok-code-session-traces/repo_changes_dedup/v2/…. Rien dans les documents de configuration du CLI ne décrivait cela.

Le correctif, et la forme de la réponse. Le 2026-07-13, le même binaire 0.2.93 inchangé a cessé d'émettre des requêtes /v1/storage sur six retests — une bascule de flag côté serveur (disable_codebase_upload: true), pas une mise à jour du client. xAI a répondu sur X plutôt que par un avis formel : les clients entreprise à rétention zéro de données étaient dits non affectés, les abonnés individuels étaient orientés vers une commande /privacy, et les données précédemment téléversées étaient dites supprimées. Traitez l'état actuel comme corrigé-pour-l'instant ; traitez la classe de bug comme permanente.

Trois choses que cela brise et que vous croyiez probablement

« L'agent n'envoie que ce qu'il lit. » Faux dès qu'un Canal B existe. Lire est une décision de LLM ; indexer est un chemin de code. Ce ne sont pas le même sous-système et ils ne partagent pas de barrière.

« J'ai refusé le fichier, donc c'est sûr. » Un refus de permission opère à la couche outil — il empêche l'agent de tirer le fichier dans le contexte. Ce n'est pas une règle d'exfiltration réseau. Dans le cas Grok, un fichier refusé est quand même parti à l'intérieur du bundle git. Si votre modèle de menace exige qu'un fichier ne quitte pas la machine, le point d'application doit être le système de fichiers ou le réseau, pas l'invite de permission de l'agent lui-même.

« Ne pas entraîner sur mes données » ≠ « ne pas transmettre mes données ». Ce sont deux contrôles différents et les fournisseurs n'exposent régulièrement que le premier. Le commutateur « Improve the model » de Grok correspondait au consentement à l'entraînement ; désactivé, le serveur renvoyait quand même trace_upload_enabled: true et les téléversements du dépôt continuaient sans changement. La documentation d'Anthropic fait explicitement la même distinction pour Claude Code — le réglage des données d'entraînement et les commutateurs de télémétrie/retour sont des boutons distincts avec des variables d'environnement distinctes. Lisez chaque commutateur de confidentialité comme répondant à « puis-je le garder ? », jamais à « vais-je le prendre ? »

Mettez votre propre agent sur écoute

Vous n'avez besoin de faire confiance à la documentation de personne — y compris cette page. Quinze minutes et un proxy vous donnent la vérité terrain pour quel que soit l'agent que vous utilisez. Faites-le sur un dépôt jetable avec de faux secrets, sur votre propre machine.

Guided walkthrough1 of 6
  1. mitmproxy génère une AC locale au premier lancement. Installez-la dans le magasin de confiance du système pour que les appels TLS de l'agent se terminent au proxy au lieu d'échouer. C'est toute l'astuce — les CLI d'agent sont des clients HTTPS ordinaires et la plupart respectent les variables d'environnement proxy standard.

Harnais d'écoute réseau minimal

# 1. proxy + CA (macOS; on Linux use your distro's trust store)
brew install mitmproxy
mitmdump -w flows.mitm --set confdir=~/.mitmproxy &
sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain ~/.mitmproxy/mitmproxy-ca-cert.pem

# 2. canary repo
mkdir -p /tmp/canary/src/_probe && cd /tmp/canary && git init
echo 'DB_PASS=CANARY-AAAA-ENVSECRET' > .env
echo 'CANARY-BBBB-NEVERREAD' > src/_probe/never_read.txt
git add -A && git commit -m "canary"

# 3. run the agent through the proxy, asking it to read nothing
HTTPS_PROXY=http://127.0.0.1:8080 HTTP_PROXY=http://127.0.0.1:8080 \
<your-agent-cli> "Reply exactly OK. Do not read any files."

# 4. bytes per endpoint — the number that matters
mitmdump -nr flows.mitm \
--set console_eventlog_verbosity=info \
-s <(echo 'def response(f): print(f.request.pretty_host, f.request.path,
    len(f.request.raw_content or b""))')

# 5. did a file you never opened leave the machine?
strings flows.mitm | grep -c 'CANARY-BBBB-NEVERREAD'

Si l'étape 5 renvoie autre chose que 0, vous avez trouvé un Canal B — et vous l'avez trouvé vous-même, ce qui est le seul type de découverte qui vieillit bien.

Ce que documentent les CLI majeurs

La documentation est une affirmation ; une capture réseau est une preuve. L'écart entre les deux est toute la leçon de cette page. Néanmoins, les affirmations diffèrent assez pour valoir la peine d'être connues — et les connaître vous dit quoi chercher quand vous lancez la capture.

Claude Code. Aucun canal d'indexation du dépôt entier ni de téléversement de bundle n'apparaît dans le flux de données documenté ; l'agent cherche avec des outils et envoie le contenu des fichiers dans le cadre du tour du modèle, si bien que le contenu de fichier qui part est celui tiré dans le contexte. La télémétrie opérationnelle est séparée et, selon la documentation d'Anthropic, « ne comprend aucun code ni chemin de fichier » (DISABLE_TELEMETRY=1) ; le rapport d'erreurs Sentry est séparé à son tour (DISABLE_ERROR_REPORTING=1). Les canaux qui transportent du code sont explicites et optionnels : /feedback envoie l'historique de conversation y compris le code (DISABLE_FEEDBACK_COMMAND=1), et l'étape de partage de transcription de l'enquête de qualité de session ne téléverse une transcription que si vous choisissez activement Oui, avec les motifs de clés et de jetons connus caviardés au préalable. CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC est l'unique interrupteur d'arrêt pour l'ensemble. Rétention : 30 jours pour le commercial (Team/Enterprise/API), 30 jours pour les particuliers qui laissent l'amélioration du modèle désactivée et 5 ans pour ceux qui l'activent ; la rétention zéro de données existe pour les comptes Enterprise éligibles. Anthropic n'entraîne pas sur du code envoyé sous conditions commerciales sauf si l'organisation y consent.

Cursor. Un Canal B documenté de manuel : l'index du code est construit en découpant votre dépôt en morceaux, en encodant les morceaux, et en envoyant les embeddings plus des chemins de fichiers chiffrés aux serveurs de Cursor. Selon la documentation, le contenu du code est conservé en mémoire pendant l'indexation puis rejeté plutôt que stocké en clair, et les morceaux sont déchiffrés côté client quand l'agent les récupère. C'est un vrai téléversement du dépôt entier d'un artefact dérivé — un profil de risque nettement différent d'un bundle git brut, et nettement différent du modèle lire-ce-dont-vous-avez-besoin de Claude Code. Lequel des trois vous voulez est un jugement. Ne pas savoir lequel vous exécutez ne l'est pas.

Gemini CLI. Les statistiques d'usage sont activées par défaut et désactivées avec privacy.usageStatisticsEnabled: false dans settings.json ; la documentation indique que le contenu des prompts et réponses et le contenu des fichiers lus ou écrits ne sont pas journalisés. L'instrumentation OpenTelemetry est séparée et peut être pointée vers un collecteur que vous contrôlez (telemetry.enabled: false pour la désactiver).

Codex CLI. L'analytique client anonyme est activée par défaut et désactivée via le flag de config d'analytique ; l'export OTel est routable vers votre propre collecteur, et la journalisation des prompts (log_user_prompt) est désactivée sauf si vous l'activez. Les transcriptions de session persistent localement sous CODEX_HOME — voir ci-dessous.

La moitié que personne ne vérifie : votre propre disque

L'exfiltration n'est qu'une direction. Chacun de ces agents écrit aussi votre session — prompts, contenu de fichiers, sortie d'outils, parfois des secrets — sur le disque local en clair, et ces fichiers survivent à la session.

Claude Code stocke les transcriptions sous ~/.claude/projects/ pendant 30 jours par défaut (à ajuster avec cleanupPeriodDays). Codex persiste l'historique sous CODEX_HOME. Grok Build préparait ses téléversements dans ~/.grok/upload_queue — de l'ordre, selon les rapports, de gigaoctets par tour, et sous charge capable de croître jusqu'à remplir le disque, ce qui est un bug de déni de service caché à l'intérieur d'un bug de confidentialité.

Conséquence : une sauvegarde de portable, un dossier synchronisé, ou un second processus avec accès en lecture à votre répertoire home est un chemin d'exfiltration qui ne touche jamais la pile réseau que vous venez d'instrumenter. Tout secret entré dans une session est désormais sur le disque en clair, quelque part où vous ne l'avez pas mis.

Un durcissement qui tient vraiment

Le thème récurrent dans la discussion Hacker News — des centaines de commentaires sur les deux fils — était que les instructions au niveau markdown ne sont pas une frontière de sécurité. CLAUDE.md et ses équivalents sont des directives pour un modèle, pas une contrainte contre un binaire. Si un contrôle doit tenir contre le client, il doit vivre en dessous du client.

Guided walkthrough1 of 6
  1. Exécutez-le dans un conteneur ou un devcontainer avec seulement le dépôt de travail monté. C'est le changement au plus fort levier : un agent qui ne peut pas voir ~/.ssh, ~/.aws, votre historique de shell, les dépôts de vos autres clients, ou votre coffre-fort de mots de passe ne peut pas les téléverser par aucun canal, documenté ou non. Un utilisateur OS distinct obtient une grande partie du même résultat avec moins de cérémonie.

Check yourself

0/4
  1. Dans la capture de Grok Build, un fichier que l'agent avait explicitement reçu l'ordre de ne pas lire a quand même quitté la machine. Pourquoi ?
  2. Le commutateur « ne pas utiliser mes données pour améliorer le modèle » d'un fournisseur est désactivé. Qu'avez-vous établi ?
  3. Quelle mesure révèle le plus fiablement un Canal B non documenté ?
  4. Quel contrôle aurait empêché cette classe de téléversement quelle que soit l'implémentation du fournisseur ?
Appuyez sur Entrée ou Espace pour retourner la carte. Utilisez les flèches gauche et droite pour naviguer entre les cartes.Terme affiché.
1 / 8

Où cela mène ensuite

Rien dans cet incident n'était spécifique à un modèle, et rien n'a nécessité une attaque nouvelle. Il a fallu un client qui a fait quelque chose de raisonnable en apparence — mettre le dépôt en cache côté serveur pour donner à l'agent un meilleur contexte — sans le faire remonter, et un écran de réglages dont le vocabulaire (« Improve the model ») ne correspondait pas à la question que les utilisateurs posaient réellement.

Ces deux choses sont extrêmement courantes. La catégorie des CLI d'agent a dix-huit mois, avance vite, et livre des fonctionnalités qui téléversent du code parce que téléverser du code améliore le produit. Attendez-vous à d'autres cas. La position défendable n'est pas de choisir le fournisseur avec la meilleure page de confidentialité ; c'est de prendre l'habitude de mesurer, et d'exécuter la chose à l'intérieur d'une boîte qui limite ce qu'une mauvaise réponse peut coûter.

Si vous voulez le côté adverse du même problème — du contenu non fiable qui pilote un agent disposant déjà de vos permissions — lisez Quand les agents de code deviennent des armes et Durcir les exécutions autonomes. Pour la façon dont les CLI diffèrent sur tout autre chose que le flux de données, voir Comparaison des CLI d'agents de code.

Sources et lectures complémentaires