En 2025, le conseil tenait en une phrase : ne collez pas votre fichier .env dans le chat. En septembre 2026, ce n’est plus un chat. C’est un harness. (data désensibilisation)
Data : La règle d’or n’a pas changé, le contexte si
Un agent de code lit des fichiers, exécute des commandes, compacte un historique, délègue à des sous-agents et, chez certains runtimes, persiste un journal rejouable. Une clé Stripe, un IBAN client, une adresse dans un CSV de recette : tout cela peut partir chez le fournisseur de modèle, puis revenir dans un commit, une URL ou un export de session.
La règle d’or n’a pas changé. Si vous ne voulez pas qu’un agent divulgue une donnée, ne la mettez pas dans son contexte. Le reste est de l’ingénierie : garder assez de forme pour que le modèle génère du bon code, et assez peu de valeur pour qu’un client ne soit pas reconstituable.

Ce qui fuit vraiment
Trois canaux distincts, souvent traités comme s’il n’y en avait qu’un.
| Canal | Exemple | Un hook d’outil suffit-il ? |
|---|---|---|
| Prompt utilisateur | Collage d’une clé ou d’un IBAN | Oui, en bloquant l’envoi |
Outils (Read, Bash, Grep) | cat .env, lecture d’un dump SQL | Oui, avant et après l’outil |
| Fichiers attachés | @customers.csv, @.env | Souvent non : le contenu est injecté dans le prompt sans appel Read |
Chez Claude Code, un hook PreToolUse sur Read ne protège pas toujours la syntaxe @fichier. Un proxy qui voit le corps HTTP de la requête API, lui, le voit.
Il faut aussi séparer trois familles de données. Le bon remplacement n’est pas le même.
| Famille | Exemples | Objectif | Remplacement utile pour le code |
|---|---|---|---|
| Secret | clé API, JWT, PEM, DATABASE_URL | Ne jamais sortir de la machine | Jeton typé côté modèle, restauration locale uniquement pour l’outil |
| PII / GDPR | IBAN, e-mail, téléphone, adresse, NIR | Minimisation, pseudonymisation | Placeholder stable ou faux réaliste déterministe |
| Donnée métier | positions de marché, CA client, contrats | Confidentialité, NDA | Schéma, volumes, distributions — pas les lignes réelles |
Tout masquer par ***REDACTED*** nuit à la qualité : le modèle ne sait plus s’il a affaire à une URL, un IBAN ou un mot de passe. Un jeton typé et stable (<IBAN_1>, sk_test_REDACTED) conserve la sémantique et coûte souvent moins de jetons qu’un dump réel.
Un filtre n’est pas une anonymisation au sens du RGPD. C’est de la minimisation et, au mieux, de la pseudonymisation. L’organisme reste responsable du traitement.
En septembre 2026 : Agent = Model + Harness
DeepSeek a popularisé une formule désormais reprise partout : l’agent, c’est le modèle plus le harness. Le modèle raisonne. Le harness voit le disque, le shell, parfois la base, et l’historique. C’est donc le harness — pas le prompt système — qui décide si une donnée quitte la machine.
Trois runtimes occupent le poste de développeur. Un quatrième empile une boucle longue par-dessus Claude Code.
| Runtime | Nature | Comment l’étendre | Fuite typique en 2026 |
|---|---|---|---|
| Claude Code | Harness éditeur | Hooks + ANTHROPIC_BASE_URL | @fichier contourne souvent PreToolUse |
| OpenCode | Harness open source, 75+ fournisseurs | Plugins TypeScript + provider.baseURL | Pas de hook API-level stable ; le body HTTP n’est pas un contrat |
DeepSeek Harness (dsh) | Preview MIT depuis août 2026, tout est plugin | Plugins Cordis + DEEPSEEK_BASE_URL | Journal de session append-only ; upload possible vers l’API ; gateway locale |
| DeepThink | Loop Engineering sur le Claude Agent SDK | Manifestes de harness versionnés + mêmes hooks Claude | Boucles longues, compactages, canaux IM (Feishu, Telegram, DingTalk) |
Trois faits d’architecture ont rendu obsolète le « petit script qui regex le dernier message ».
- Le contexte modèle est reconstruit depuis un journal, pas depuis le seul tour courant. DeepSeek Harness le formalise : ce qui est visible du modèle doit pouvoir être relu dans le session log. Redacter l’appel HTTP et laisser l’IBAN dans le JSONL, c’est le renvoyer au compactage, au fork ou au replay.
- Les appels d’outils ne sont plus du texte plat. Les arguments voyagent en JSON. Le mode Code de DeepSeek Harness va plus loin : le modèle écrit un programme TypeScript qui orchestre plusieurs outils en un aller-retour. Un filtre qui ne scanne que le message utilisateur laisse l’IBAN dans
tool_calls[].function.arguments. - Le harness multiplexe les fournisseurs. OpenCode bascule d’Anthropic à Gemini ou Ollama. Une politique « Claude only » est un trou.
Une architecture en couches, pas un outil miracle
[0] Contrat et classification (ZDR, DPA, Public / Interne / Restreint)
[1] La donnée n’est pas dans le workspace (coffre, pas de .env dans le repo)
[2] L’agent n’a pas le droit (deny, ignore, sandbox)
[3] La donnée est fausse (bouchons, fixtures, clone de base)
[4] Si elle passe, elle est masquée (hooks / plugins + proxy)
[5] Si c’est inévitable : broker, identifiants courts, modèle local, humainChaque couche réduit le résidu que la suivante doit traiter. C’est aussi ce qui protège contre les faux négatifs des expressions régulières.
Niveau 1 — Le bouchon, encore la meilleure idée
C’est la première solution à poser. Elle coûte zéro jeton sensible et produit souvent meilleur code qu’un dump réel.
.env.example # clés présentes, valeurs fictives
testdata/customers.csv
fixtures/payment.json
docker-compose.yml # mot de passe = changemeLes fichiers .env, *.pem et credentials.json sont gitignorés et, si possible, hors du répertoire indexé par l’agent.
Pour qu’un modèle génère un parseur IBAN ou un client Stripe correct, donnez-lui des faux valides : domaines example.com, IBAN de documentation ISO, cartes de test Stripe, e-mails réservés par la RFC 2606. Le modèle reconnaît le format et le checksum ; il n’a pas besoin de Mme Dupont.
Complétez par une règle d’agent dans CLAUDE.md ou l’équivalent OpenCode : secrets uniquement via les variables d’environnement, exemples dans testdata/, jamais de PII réelle. Ce n’est pas une barrière de sécurité. C’est un biais de génération. Le filet réel, en CI, reste gitleaks, TruffleHog et la protection de push GitHub.

Niveau 2 — Empêcher l’accès
Chez Claude Code, combinez une liste d’interdiction et un fichier d’ignore :
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Read(./**/*.pem)"
]
}
}
Vérifiez réellement le comportement (« quels fichiers d’environnement vois-tu ? »). Les fichiers d’ignore ont déjà eu des bugs. Ce n’est pas une frontière de sécurité.
Chez OpenCode, un plugin tool.execute.before refuse read et bash sur les chemins sensibles. Chez DeepSeek Harness, le bac à sable démarre en lecture seule (bubblewrap, Landlock ou Seatbelt). Utile. Insuffisant : lire customers.csv en lecture seule envoie quand même les lignes au fournisseur.
Le pattern le plus robuste pour les secrets d’exécution reste le courtier : l’agent n’a pas la clé ; un sidecar l’injecte sur le dernier saut HTTP. Un identifiant que l’agent peut lire est un identifiant que l’agent peut fuiter.
Niveau 3 — Hooks et plugins : légers, natifs, incomplets
Claude Code
| Événement | Bloquer | Réécrire | Usage |
|---|---|---|---|
UserPromptSubmit | Oui | Souvent non | Collage accidentel de clé : refuser et proposer le texte déjà nettoyé |
PreToolUse | Oui | Oui | Interdire Read .env ; pointer vers une copie masquée |
PostToolUse | Oui | Oui | Nettoyer la sortie de cat / grep avant le modèle |
Le bon schéma s’appelle coffre de session :
- À l’entrée,
sk_live_abcdevient<STRIPE_SECRET_1>. - La bijection reste en mémoire de session, jamais sur disque.
- Avant
BashouEdit, le jeton redevient la valeur réelle localement. - Le transcript et l’API ne voient que le jeton.
Le modèle écrit curl -H "Authorization: Bearer <STRIPE_SECRET_1>". Le hook réinjecte. La commande fonctionne. Le fournisseur n’a jamais vu la clé.
Deux couches de détection, pas une : d’abord les valeurs exactes lues dans l’environnement et les fichiers .env (zéro faux positif), ensuite les formes connues (gitleaks, TruffleHog) et, pour l’Union européenne, IBAN (mod 97), NIR, SIRET, TVA intra-communautaire. Les catalogues américains (SSN, ZIP) ne suffisent pas.
Sur certaines versions de Claude Code, le matcher * ne se déclenche pas. Préférez une chaîne vide ou la liste explicite des outils.
OpenCode
OpenCode n’est pas un clone de Cursor. C’est un serveur headless, des fronts (terminal, web, bureau, IDE) et des plugins. Les fournisseurs se configurent dans opencode.json via provider.*.options.baseURL. Un proxy s’injecte par fournisseur.
| Levier | Voit | Fiabilité, septembre 2026 |
|---|---|---|
tool.execute.before | Arguments d’outil | Stable. Deny .env, restauration de jetons |
tool.execute.after | Sortie d’outil | Stable. Nettoyage de read, bash, grep |
experimental.chat.messages.transform | Messages avant l’API | Expérimental. Déjà sujet à des régressions. Pas une barrière unique |
provider.options.baseURL | Corps HTTP | Le plus fiable pour la couverture |
Une demande de hooks PreApiCall / PostApiCall au niveau Provider est ouverte depuis mars 2026. Tant qu’ils ne sont pas livrés et stables, le duo raisonnable reste plugin + proxy.
Côté plugins, trois strates se distinguent.
Couche A — réversible, pensée agent. @rehydra/opencode remplace PII et secrets par des balises typées (<PII type="IBAN" id="1"/>), explique au modèle que ces balises sont des valeurs, restaure les secrets dans les arguments d’outils, et relit les valeurs pour l’humain seulement. Les URL et adresses IP sont désactivées par défaut : sinon localhost:3000 devient un faux positif permanent.
Couche B — deny et audit. opencode-warden (v1.3) apporte une soixantaine de motifs, le blocage de chemins, des exemptions par fichier (un exemple Stripe peut garder sk_test_), et la protection en écriture y compris via tee et les redirections.
Couche C — filet léger. opencode-redactor (regex + entropie) et opencode-log-sanitizer (JWT, bcrypt, gros base64) réduisent le bruit. Ils ne remplacent pas un reconnaisseur d’IBAN métier.
Méfiez-vous des plugins qui promettent HIPAA, SOC 2 et PCI « out of the box ». Un masque n’est pas une certification. Exigez un échec fermé : si le filtre plante, l’appel ne part pas.
DeepSeek Harness
Preview MIT depuis le 13 août 2026. Kernel Cordis : modèles, outils, compétences, sessions, bacs à sable, stockage, la boucle elle-même et l’interface sont des plugins. Quatre presets : Standard, Code, Minimal, Creator.
Quatre points d’attention pour un RSSI ou un DBA.
- Le journal de session n’est pas un log d’appoint. C’est la source du contexte modèle. Il faut masquer avant l’append, pas seulement au moment de l’appel HTTP.
- Le plugin officiel d’upload de session log peut envoyer le journal canonique à l’API DeepSeek. Ce n’est pas injecté dans
messages, mais cela quitte la machine. Hors contrat explicite, désactivez-le. C’est une décision de transfert, pas un détail de télémétrie. - Le mode Code génère un programme TypeScript. Le filtre doit scanner ce source comme un fichier lu.
- La passerelle web locale (
127.0.0.1:3080) est une surface RPC privilégiée. Ne la liez pas sur toutes les interfaces. Un débat public de 2026 documente déjà des scénarios d’échappement via cette gateway non authentifiée.
Un plugin Cordis sérieux tient un coffre mémoire par identifiant de session, écrit dans le journal la version déjà masquée, ne journalise jamais la bijection, et refuse l’appel si le redactor est indisponible.
DeepThink
DeepThink n’est pas un quatrième filtre. C’est une plateforme de boucles longues au-dessus du SDK Claude. On y impose la même stack (hooks + ANTHROPIC_BASE_URL vers le proxy) dans chaque conteneur agent. On versionne le manifeste de harness pour pouvoir revert une régression de hook. On n’achemine pas un transcript en clair vers un robot de messagerie : le canal IM est un exfiltrateur.
Niveau 4 — Le proxy, couche de vérité
Le hook vit dans le runtime. Le proxy voit le fil.
Claude Code / OpenCode / dsh / DeepThink
│
▼
localhost:8787 redact requête · coffre RAM · unredact réponse
│
▼
Anthropic / OpenAI / DeepSeek / vLLM interne
Cinq plans, pas un nginx qui applique une regex.
- Admission — authentification, échec fermé si le moteur de masquage est down.
- Parse — messages,
tool_callsJSON, pièces jointes texte, source généré en mode Code. - Détection — valeurs exactes d’environnement, motifs gitleaks, IBAN mod 97, Presidio étendu FR (NIR, SIRET).
- Transformation — jeton, faux déterministe, masque ou refus, selon le type.
- Routage — cloud désensibilisé, ou bascule vers un modèle on-premise si le ticket exige le réel.
Quatre modes de remplacement
| Mode | Exemple | Qualité du code | Lecture GDPR |
|---|---|---|---|
| Jeton stable | FR76… → <IBAN_1> | Bonne si le modèle apprend le tag | Pseudonymisation |
| Faux déterministe | même empreinte → toujours le même IBAN checksummé | La meilleure pour les parseurs et les tests | Pseudonymisation tant que la bijection existe |
| Masque | ****7890 | Mauvaise pour un validateur | Adapté aux cartes |
| Refus | requête bloquée | — | Secrets, NIR, dumps entiers |
Règle de DBA : les identifiants de jointure (customer_id, RUM de mandat) se tokenisent de façon déterministe d’une table à l’autre. Les payloads (IBAN, e-mail, adresse) se fakent. Les secrets se masquent sans restauration dans le chat.
Quoi brancher
| Brique | Rôle | Licence / posture |
|---|---|---|
| PrivAiTe | Proxy PII et secrets, y compris arguments d’outils et multimodal | BSD-3, self-host, gateway Claude Code / Codex |
| rdx (claude-code-redact) | Proxy ou hooks, restauration de fichiers, règles par projet | Apache-2.0 |
| LiteLLM + Presidio | Passerelle d’équipe, MASK / BLOCK, hooks MCP | Déjà le plan de contrôle de beaucoup de SI |
| LiteLLM Sensitive Data Routing | Si PII détectée, bascule vers un modèle on-premise, session collante | Plus honnête que démasquer le cloud |
| Philter AI Proxy | PII / PHI et piste d’audit | À coller devant le gateway, pas à la place |
LiteLLM, en 2026, n’est plus un simple routeur de clés. Testez toutefois le chemin agent : des modes « logs seulement » ont déjà corrompu la réponse visible avec des jetons <PERSON>.
Déploiement type pour une équipe de quinze à quatre-vingts développeurs : sidecar sur le poste (coffre en RAM, faible latence), LiteLLM dans le VPC (quota, traces sans clair, bascule on-prem), jamais de table de réidentification dans les journaux applicatifs. Tous les fournisseurs cloud pointent vers le même proxy. Un modèle local peut rester en direct si le contrat l’autorise.
Hooks contre proxy
| Critère | Hooks / plugins | Proxy local |
|---|---|---|
| Installation | Fichier de settings et script | Processus et URL de base |
Couverture @fichier / corps API | Faible | Forte |
Bloquer Read .env | Excellente | Indirecte (contenu déjà masqué) |
Restaurer un secret pour curl | Naturelle | Possible si le proxy restaure les arguments d’outils locaux |
| Multi-outils | À recoder | Un endpoint |
| Échec | Souvent ouvert (l’appel part) | Doit être fermé |
Les deux. Les hooks empêchent l’accès et restaurent les secrets d’exécution. Le proxy est la dernière ligne avant Internet, y compris ce que les hooks ratent.
Niveau 5 — La base métier, du plus sûr au plus risqué
Le proxy sauve ce qui fuit au fil de l’eau. Une copie de production mal faite pollue tous les tours.
Pipeline de clone, version pragmatique :
production (instantané lecture)
→ sous-ensemble (période, entité, fraction de lignes)
→ transformation par colonne
clés : jeton HMAC déterministe (jointures préservées)
IBAN : faux du même pays, checksum mod 97
e-mail : {empreinte}@example.test
adresse : Faker fr_FR, code postal cohérent
montant : bruit léger, ou inchangé si le bug est monétaire
texte libre : Presidio + reconnaisseurs NIR / SIRET / IBAN
→ chargement app_dev, réseau isolé
→ tests de réidentification
→ identifiants app_dev dans le coffre, jamais dans le workspace agent

Outils éprouvés : extension PostgreSQL Anonymizer, Greenmask, Neosync, Faker, Presidio avec spaCy français et reconnaisseurs métier. Presidio « vanille » est calé sur les identifiants américains. Ne pas l’utiliser en Europe sans extension.
Rappel juridique : une copie masquée par hash ou substitution reste souvent de la pseudonymisation, donc des données personnelles. Seules des données synthétiques de novo, non reliables à une personne, avec tests de distance au plus proche enregistrement, sortent du régime — et encore, avec documentation.
Quand le clone est bien fait, le proxy ne sert plus qu’aux secrets, aux journaux collés et au CSV oublié dans /tmp. C’est l’état stable visé.
Quand le réel est inévitable
Il existe des tickets où « tout synthétiser » est un mensonge : un IBAN d’un pays rare, un nom à particule qui casse l’encodage, un réglement de marché, un incident.
Alors on ne « démasque » pas le proxy. On change de modèle.
LiteLLM propose un garde-fou de routage : dès qu’une donnée sensible apparaît, la session entière bascule vers un modèle on-premise pendant une durée limitée. Le cloud ne voit rien. Le modèle local voit un extrait minimal — une ligne, pas la table.
Compléments non négociables : identifiants courts, courtier plutôt que fichier d’environnement dans le processus agent, session jetable, pas d’export de transcript, pas de navigation web dans la même session, humain pour toute écriture en production. Le modèle décide l’intention (refund(order_id)). Le code déterministe porte les secrets.
Recette d’équipe
Semaine 1 — hygiène. .gitignore, ignore de l’agent, interdiction de lire .env, fichier d’exemple, jeu testdata/, scanner de secrets en pré-commit, compte fournisseur avec zéro rétention si le code est propriétaire.
Semaine 2 — hooks et plugins. Blocage des collages de clés, deny des chemins, remplacement des valeurs d’environnement exactes après chaque outil. Chez OpenCode : Rehydra plus Warden. Chez DeepSeek Harness : sandbox lecture seule et coupure de l’upload de journal.
Semaine 3 — proxy. Sidecar local, règles IBAN / e-mail / téléphone / secrets, échec fermé, vérification des arguments d’outils JSON, même URL pour tous les fournisseurs cloud.
Quand le métier arrive. Pipeline Faker ou Anonymizer vers app_dev. L’agent n’a que l’URL de cette base. Procédure écrite pour l’extrait réel irréductible.
Contrôles d’acceptation
Un filtre non testé est un filtre ouvert. À jouer dans la CI du poste ou de l’image agent.
- Coller une clé
sk-ant-…: absente de la capture réseau (empreinte seulement dans l’audit). read .env: refusé, ou valeurs remplacées.- Attacher un CSV de vingt IBAN : aucun IBAN réel dans le corps API.
- Tenter
psql -c "select * from customers": bloqué, ou sortie déjà masquée dans le journal. - Générer un
curlavec un jeton de secret : la commande locale a la vraie clé, le transcript non. - Compactage, fork, export de session : pas de clair.
- Proxy arrêté : aucun appel sortant.
- Changement de fournisseur : même politique sur le cloud.
Dix pièges

- Tout masquer en étoiles : le modèle invente des formats faux.
- Faux non déterministes : les identifiants changent à chaque tour, le code ne compile plus.
- Envoyer dix mégaoctets de CSV « déjà masqué » : vous payez les jetons, le modèle se noie.
- Restaurer les secrets dans la réponse de chat : le transcript refuit.
- Un hook qui écrit son entrée JSON dans un fichier de débogage.
- Croire qu’un fichier d’ignore est une frontière de sécurité.
- Presidio sans reconnaisseur IBAN ou NIR.
- Proxy exposé sur le réseau local sans jeton.
- Échec ouvert : un plantage du filtre égale une fuite.
- Demander au cloud d’anonymiser la PII : c’est déjà un transfert.
Politique minimale à versionner avec le repo
secrets:
action: redact
restore: tool_args_only
sources: [env, dotenv, gitleaks]
pii:
iban: { action: tokenize, stable: true, validate: mod97 }
email: { action: fake, domain: example.com, stable: true }
phone: { action: tokenize, stable: true }
address: { action: fake, locale: fr_FR, stable: true }
name: { action: fake, stable: true }
allowlist:
- "*@example.com"
- "sk_test_*"
never_send:
paths: [".env", "secrets/", "*.pem", "prod-dumps/"]
Ce que septembre 2026 change dans la doctrine
Le plugin natif — hooks Claude, Rehydra, Warden, plugin Cordis — est nécessaire et insuffisant. Il gère la séparation entre décider et faire, et la restauration d’outils. Il ne voit pas tout le fil.
Le proxy de désensibilisation est la couche de vérité pour tout ce qui est cloud. Il doit parler JSON d’outils, pas seulement du chat.
Le journal de session est un traitement au sens du RGPD, surtout s’il est envoyé à un fournisseur. On le coupe, on le chiffre, ou on le masque à l’écriture.
La base de développement reste le meilleur proxy. Un clone bien fait rend le reste banal.
Lorsque le réel est inévitable, on route vers l’on-premise. On ne baisse pas la politique.
Aucun de ces dispositifs n’est une mise en conformité à lui seul. Ensemble, ils transforment un harness qui aspire le poste de travail en un système dont le cloud ne reçoit que des formes, des schémas et des faux déterministes — assez pour générer du bon code, trop peu pour reconstituer un client.
Références et liens
Documentation officielle
- Claude Code — Hooks reference : https://code.claude.com/docs/en/hooks
- OpenCode — Providers : https://opencode.ai/docs/providers/
- DeepSeek Harness — session-log-deepseek : https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-log-deepseek/README.md
- LiteLLM — Sensitive Data Routing : https://docs.litellm.ai/docs/proxy/guardrails/sensitive_data_routing
Plugins et outils de sécurité
- Rehydra OpenCode Plugin : https://docs.rehydra.ai/guides/opencode-plugin
- opencode-warden (npm) : https://www.npmjs.com/package/opencode-warden
- claude-code-redact (rdx) : https://github.com/douganderson444/rdx
- PrivAiTe : https://github.com/crp4222/PrivAiTe
- Philter AI Proxy : https://philterd.github.io
Anonymisation et masking
- PostgreSQL Anonymizer : https://postgresql-anonymizer.readthedocs.io/
- Greenmask : https://github.com/GreenmaskIO/greenmask
- Neosync : https://github.com/nucleuscloud/neosync
- Microsoft Presidio : https://microsoft.github.io/presidio/
- spaCy fr_core_news_lg : https://spacy.io/models/fr
Référentiels et cadres
- OWASP Top 10 for LLM Applications (2025) : https://genai.owasp.org/llm-top-10/
- OWASP Agentic AI — Threats and Mitigations : https://genai.owasp.org/resource/agentic-ai-threats-and-mitigations/
- NIST AI Risk Management Framework : https://www.nist.gov/itl/ai-risk-management-framework
- ISO/IEC 42001:2023 — AI Management System : https://www.iso.org/standard/81230.html
Demande de fonctionnalité en cours
- Claude Code — PreApiCall / PostApiCall hooks (issue #39882) : https://github.com/anthropics/claude-code/issues/39882
Pascal Froment Setp. 2026