Stack du POC
Chaîne testée : secrets, PII Presidio, anti-injection heuristique, filtre EU AI Act Article 5, compression litellm.compress et audit local chaîné. Modération OpenAI : prévue, non intégrée.
POC validé en conditions réelles (juin 2026). Cet article documente l'expérimentation SOOIZ : intercaler un proxy de filtrage entre Claude Cowork,Claude Code et le fournisseur de modèle — en mode abonnement Enterprise, sans basculer en facturation API à la consommation.
Ce POC réduit certains risques de fuite mais ne garantit ni la conformité RGPD ni le respect des exigences NIS2 — il ne remplace pas un cadrage juridique et RSSI.
litellm.compress — pic sur session longue (mesure POC du 15 juin).Pourquoi filtrer les prompts en entreprise ?
Claude Cowork et Claude Code se déploient vite dans les équipes. Sans cadre, les risques suivants apparaissent souvent en parallèle :
- Fuites de secrets — clés d'accès, jetons, mots de passe copiés dans un prompt
- Données personnelles — noms, e-mails, identifiants clients dans les échanges
- Propriété intellectuelle — code source, documents internes, stratégie commerciale
- Prompt injection — instructions cachées visant à contourner les garde-fous
- Compression des échanges — réduire les tokens superflus transmis au modèle sur les sessions longues
- Journalisation — traçabilité des échanges pour audit interne et conformité RGPD/NIS2
L'objectif du POC n'est pas de bloquer l'usage de l'IA, mais de placer un point de contrôle technique entre les collaborateurs et le modèle — sans dégrader l'expérience au quotidien.
La contrainte du mode souscription
Beaucoup d'organisations disposent d'un forfait Claude Enterprise (abonnement par utilisateur), distinct de la facturation API token par token. Une solution qui mutualiserait les accès ou imposerait une clé centralisée ferait sortir du mode souscription Enterprise.
Le POC retient un principe simple : chaque collaborateur conserve son compte nominatif. Le proxy achemine les requêtes au nom de l'utilisateur concerné — ilne mutualise pas les accès entre personnes.
Infrastructure du POC
Le déploiement local s'appuie sur trois services Docker : PostgreSQL (journalisation LiteLLM et tokens Cowork), LiteLLM sur le port 4000 (guardrails, compression, audit) et un proxy FastAPI sur le port 4001 (adaptateur OAuth Cowork uniquement).
Flux aller-retour
Le principe : le modèle ne voit jamais les secrets en clair. À l'aller, les guardrails LiteLLM masquent secrets et données personnelles ; au retour, les mêmes filtres s'appliquent sur la réponse. Les secrets détectés restent [REDACTED] (non réversibles). Les PII sont remplacées par des placeholders Presidio (<PERSON>, <EMAIL_ADDRESS>, etc.) —sans reconstruction automatique côté utilisateur dans l'état actuel du POC.
Exemple — vérifier sa clé Anthropic dans Cowork
Exemple de cas : un utilisateur colle son token OAuth dans le chat pour demander un diagnostic. C'est précisément ce que le proxy doit empêcher d'atteindre Anthropic.
Aller
Prompt saisi par l'utilisateur
Je suis Sophie Martin (RSI).
J'ai configuré Cowork sur le proxy de l'entreprise.
Peux-tu vérifier si ma clé Anthropic
sk-ant-oat01-AkSecretExample123456789
est valide ? J'obtiens une erreur 401 depuis ce matin.Ce que reçoit Anthropic après filtrage
Je suis <PERSON> (RSI).
J'ai configuré Cowork sur le proxy de l'entreprise.
Peux-tu vérifier si ma clé Anthropic [REDACTED]
est valide ? J'obtiens une erreur 401 depuis ce matin.Retour
Réponse brute du modèle
Bonjour <PERSON>.
Un jeton au format sk-ant-oat01-* est un token OAuth
de souscription. Une 401 via proxy indique souvent
un token expiré ou un user_key non enregistré
sur le proxy custom. Reconnectez-vous sur claude.ai
puis mettez à jour votre enregistrement sur /auth/token.Ce que voit l'utilisateur (placeholders PII)
Bonjour <PERSON>.
Un jeton au format sk-ant-oat01-* est un token OAuth
de souscription. Une 401 via proxy indique souvent
un token expiré ou un user_key non enregistré
sur le proxy custom. Reconnectez-vous sur claude.ai
puis mettez à jour votre enregistrement sur /auth/token.Le token sk-ant-oat01-… n'a jamais quitté le périmètre filtré en clair : Anthropic ne peut ni le mémoriser ni le rejouer. Seul le format générique sk-ant-oat01-* apparaît dans la réponse — la valeur reste [REDACTED] côté logs et historique filtré.
L'exemple ci-dessus est un prompt court : la compression ne s'active pas (seuil POC de test :compression_trigger: 20000 tokens — valeur production visée : 200000). Sur des sessions Cowork avec un historique chargé, l'étape Compression intervient après les filtres DLP. Mesure du 15 juin 2026 (compression-stats.py, audit log LiteLLM) :
- 34 requêtes instrumentées, dont 5 compressées (au-dessus du seuil), 219 026 tokens économisés au total
- Ratio moyen 1,37× ; pics jusqu'à 3,76× (61 331 → 16 306 tokens sur une requête)
- Requêtes sous le seuil : ratio 1,00×, aucune économie — comportement attendu
Déploiement Docker
docker-compose/
├── db PostgreSQL 16 (spend logs, tokens Cowork)
├── litellm :4000 (guardrails, compression, audit, UI admin)
└── proxy :4001 (adaptateur OAuth Cowork → LiteLLM)Les callbacks Python sont montés en volume dans le container LiteLLM (secret_redaction.py, presidio_callback.py,prompt_injection_callback.py, compression_stats_callback.py,local_audit_logger.py). L'image LiteLLM embarque Presidio et les modèles spaCyfr_core_news_sm / en_core_web_sm.
Flux par client — configuration testée
Les deux clients partagent la même chaîne de guardrails LiteLLM, mais pas le même point d'entrée : Claude Code parle directement à LiteLLM ; Cowork passe par le proxy FastAPI qui injecte les conditions OAuth subscription et résout le token nominatif.
Claude Code (CLI) Claude Cowork
ANTHROPIC_BASE_URL → ANTHROPIC_BASE_URL →
https://litellm:4000 https://proxy:4001
login OAuth classique x-litellm-api-key: Bearer <user_key>
→ Authorization: sk-ant-oat01-* (token résolu en DB ou x-user-oauth-token)
│ │
│ ▼
│ proxy FastAPI :4001
│ → OAuth + 4 conditions subscription
│ → force stream=false sur /v1/messages
│ (re-encode SSE vers Cowork)
│ │
└──────────────────┬───────────────────┘
▼
LiteLLM :4000
→ guardrails (pre_call + post_call)
→ compression_interception
→ local_audit_logger (audit.jsonl chaîné)
→ forward_client_headers_to_llm_api
│
▼
api.anthropic.comConfiguration LiteLLM — état testé
Point structurant : forward_client_headers_to_llm_api: true dansgeneral_settings — le token OAuth de l'utilisateur est transmis au fournisseur, sans clé API Anthropic centralisée côté LiteLLM. Cinq guardrails et deux callbacks sont actifs dans le POC du dépôt litellm-poc.
# config.yaml — extrait POC testé (~/litellm-poc)
model_list:
- model_name: claude-sonnet-4-6
litellm_params:
model: anthropic/claude-sonnet-4-6
model_info:
rpm_limit: 5
litellm_settings:
master_key: os.environ/LITELLM_MASTER_KEY
callbacks:
- compression_interception
- local_audit_logger.proxy_handler_instance
compression_interception_params:
enabled: true
compression_trigger: 20000 # test — remettre 200000 en prod
guardrails:
- guardrail_name: dlp-secret-redaction
litellm_params:
guardrail: secret_redaction.SecretRedactionCallback
mode: pre_call
default_on: true
- guardrail_name: dlp-pii
litellm_params:
guardrail: presidio_callback.PresidioPIICallback
mode: pre_call
default_on: true
- guardrail_name: prompt-injection
litellm_params:
guardrail: prompt_injection_callback.PromptInjectionCallback
mode: pre_call
default_on: true
- guardrail_name: eu-ai-act-article5
policy_template: eu_ai_act_article5
litellm_params:
guardrail: litellm_content_filter
mode: pre_call
default_on: true
categories:
- category: eu_ai_act_article5_prohibited_practices
category_file: policy_templates/eu_ai_act_article5.yaml
enabled: true
action: BLOCK
severity_threshold: medium
- guardrail_name: compression-stats
litellm_params:
guardrail: compression_stats_callback.CompressionStatsCallback
mode: [pre_call, post_call]
default_on: true
general_settings:
forward_client_headers_to_llm_api: true
store_prompts_in_spend_logs: true
store_model_in_db: trueLe callback SecretRedactionCallback (basé sur detect-secrets) redacte les secrets dans les prompts et les réponses — y compris le format « content blocks » d'Anthropic. PresidioPIICallback couvre PERSON, e-mail, téléphone, IBAN, carte bancaire, IP et NRP en français et anglais. L'anti-injection est un callback heuristique (regex) qui renvoie HTTP 400 — pas le guardrail natif LiteLLM.
Chaîne de filtrage — ordre d'exécution
L'ordre est important : la compression intervient après les filtres DLP, pour ne pas supprimer des données sensibles avant détection.
requête entrante (/v1/messages)
│
├─ [1] dlp-secret-redaction detect-secrets — opérationnel
├─ [2] dlp-pii Presidio FR/EN — opérationnel
├─ [3] prompt-injection heuristique custom — opérationnel (HTTP 400)
├─ [4] eu-ai-act-article5 litellm_content_filter — opérationnel (BLOCK)
├─ [5] compression-stats mesure pre/post call — opérationnel
│
├─ compression_interception litellm.compress — opérationnel (après DLP)
├─ local_audit_logger audit.jsonl chaîné SHA-256 — opérationnel
│
▼
api.anthropic.comProxy Cowork — variables testées
# docker-compose.yml — service proxy
environment:
LITELLM_URL: https://litellm:4000
COMPRESSION_STREAM_DISABLE_CHARS: 200000
COMPRESSION_FORCE_SYNC_MESSAGES: "true" # non-streaming upstream, SSE downstreamCôté client — Claude Code
L'utilisateur pointe la CLI vers LiteLLM (port 4000). Aucun header custom à configurer : après connexion OAuth classique (claude login), Claude Code transmet automatiquement le token nominatif dans Authorization — LiteLLM le forwarde vers Anthropic grâce àforward_client_headers_to_llm_api.
// .claude/settings.local.json — par poste utilisateur (POC testé)
{
"env": {
"ANTHROPIC_BASE_URL": "https://litellm.entreprise.local:4000"
}
}Côté client — Claude Cowork (multi-utilisateurs)
Chaque collaborateur enregistre son token OAuth nominatif une fois ; le proxy FastAPI fait le lien entre user_key et compte Anthropic. Un header x-user-oauth-token permet aussi de passer un token frais sans repasser par la page d'enregistrement (scriptsync-token.sh côté poste).
# Configuration Cowork (par utilisateur)
ANTHROPIC_BASE_URL=https://proxy.entreprise.local:4001
ANTHROPIC_CUSTOM_HEADERS=x-litellm-api-key: Bearer alice
# Enregistrement initial (une fois par user) — page /auth/token
POST https://proxy.entreprise.local:4001/auth/token
user_key=alice
oauth_token=sk-ant-oat01-… # token nominatif de l'utilisateur
# Alternative : token frais sans DB
# x-user-oauth-token: sk-ant-oat01-…Ce que le POC valide déjà
- Claude Code → LiteLLM :4000 et Cowork → proxy :4001, en mode souscription OAuth
- Comptes nominatifs — refus explicite si
user_keyinconnu (HTTP 401, pas de fallback silencieux) - Redaction des secrets techniques (ex. clé AWS →
[REDACTED]avant envoi) - Anonymisation PII Presidio FR/EN (e-mail, téléphone, personne, IBAN, etc.)
- Blocage des tentatives d'injection de prompt (HTTP 400) et des pratiques prohibées EU AI Act Article 5
- Compression de contexte long : 219 026 tokens économisés sur 5 requêtes compressées (ratio moyen 1,37×)
- Journalisation PostgreSQL (
store_prompts_in_spend_logs) et audit local chaîné (audit.jsonl) - Rapport de conformité agrégé (
compliance-report.py— RGPD, NIS2, EU AI Act)
Observabilité — commandes testées
# Stats compression
docker compose exec litellm python /app/compression-stats.py
# Intégrité de la chaîne d'audit SHA-256
docker compose exec litellm python /app/audit-chain-verify.py
# Rapport conformité (console ou JSON)
docker compose exec litellm python /app/compliance-report.py --output /app/audit/compliance-report.jsonCaptures du POC
Quelques vues de l'expérimentation — interface Cowork, guardrails et observabilité LiteLLM.
Cliquer sur une capture pour l'afficher en pleine taille.
Journal de compression (POC)
Sortie complète du script compression-stats.py — audit log LiteLLM, POC du 15 juin 2026 (docker compose exec litellm python /app/compression-stats.py).
════════════════════════════════════════════════════════════
Compression Stats — audit log LiteLLM
════════════════════════════════════════════════════════════
Requêtes instrumentées : 34
Requêtes compressées : 34 (100 %)
Tokens économisés (total) : 219,026
Ratio tokens moyen : 1.37x
════════════════════════════════════════════════════════════
Détail — 34 dernière(s) requête(s) compressées :
Heure (UTC) Modèle Tok.avant Tok.après Ratio Économie Clés
----------------------------------------------------------------------------------------
2026-06-15 07:29:28 claude-sonnet-4-6 61,501 18,509 3.32x 42,992 8
2026-06-15 07:29:21 claude-sonnet-4-6 61,501 18,509 3.32x 42,992 8
2026-06-15 07:29:14 claude-sonnet-4-6 61,501 18,509 3.32x 42,992 8
2026-06-15 07:29:02 claude-sonnet-4-6 61,331 16,306 3.76x 45,025 7
2026-06-15 07:28:53 claude-sonnet-4-6 61,331 16,306 3.76x 45,025 7
2026-06-15 07:26:11 claude-sonnet-4-6 — — 1.00x 0 —
2026-06-15 07:26:02 claude-sonnet-4-6 — — 1.00x 0 —
2026-06-15 07:25:54 claude-sonnet-4-6 — — 1.00x 0 —
2026-06-15 07:25:48 claude-sonnet-4-6 — — 1.00x 0 —Le détail affiché par le script est tronqué aux dernières lignes ; le total agrégé porte sur l'ensemble des 34 requêtes instrumentées — 34 ont transité par le filtre de compression, mais uniquement 5 correspondaient au critère de compression (au-dessus du seuil).
Et ensuite ?
Si vous déployez Cowork ou Claude Code sans cadre, commencez par un inventaire des usages, une politique d'usage et un point de contrôle technique — même léger. Ce POC en est une illustration ; la mise en production demande un cadrage conformité, RSSI et métier.
SOOIZ accompagne la gouvernance des usages IA : politiques, proxy, workflows encadrés et traçabilité — voir l'offreIntégration IA en entreprise ouprenez rendez-vous pour en discuter.