Actu/Blog
IA entreprisecybersécuritélitellmsouscriptionsproxyRGPDNIS2CRA

POC — filtrer les prompts utilisateurs Cowork et Claude Code en mode souscription

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.

Schéma simplifié : Claude Cowork passe par le proxy FastAPI, Claude Code par LiteLLM, puis le fournisseur
Vue d'ensemble — Cowork via proxy :4001, Code directement sur LiteLLM :4000 ; compte nominatif par personne.
Illustration compression : 61 331 tokens réduits à 16 306, ratio 3,76x, 219 026 tokens économisés sur 5 requêtes compressées
Compression litellm.compress — pic sur session longue (mesure POC du 15 juin).
Cowork — saisie en clair, réponse avec placeholders anonymisés. Cliquer pour agrandir.

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.

Schéma aller-retour : prompt Code ou Cowork, filtrage LiteLLM, Anthropic, puis reconstruction vers l'utilisateur
Aller et retour — le fournisseur ne reçoit jamais les secrets en clair.

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.com

Configuration 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: true

Le 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.com

Proxy 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 downstream

Cô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_key inconnu (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.json

Captures du POC

Quelques vues de l'expérimentation — interface Cowork, guardrails et observabilité LiteLLM.

Cliquer sur une capture pour l'afficher en pleine taille.

Cowork — redaction d'une clé AWS et blocage d'une injection de prompt.
LiteLLM — détail d'une requête après anonymisation PII.
LiteLLM — journal des appels (observabilité).
LiteLLM — rejet d'une requête (injection de prompt détectée).

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.

Échanger sur la gouvernance IA en entreprise

Un premier échange de 30 minutes suffit pour voir si nos approches correspondent à vos enjeux.

Prendre rendez-vous