Guide technique

Les 9 endroits où ton système IA laisse fuir des données (et comment colmater chacun)

Cartographie systématique de chaque point de fuite de données dans les systèmes IA. Prompts, embeddings, logs, appels d'outils, mémoire d'agent, messages d'erreur, cache, données de fine-tuning et transferts entre agents.

13 février 202616 min de lectureÉquipe d'Ingénierie Oronts

Pourquoi le chiffrement ne suffit pas

La réponse classique à "notre système IA traite des données sensibles" est "on va chiffrer." Le chiffrement protège les données au repos et en transit. Il ne fait rien pour les données en cours de traitement. Dès que ton application déchiffre les données client pour construire un prompt, ces données sont exposées au fournisseur du LLM, intégrées dans des vector stores, écrites dans les logs, transmises via des appels d'outils, mises en cache en mémoire et stockées dans les rapports d'erreurs.

Les systèmes IA laissent fuir des données d'une manière que les applications traditionnelles ne connaissent pas. La surface d'attaque n'est pas le réseau ni la base de données. C'est le pipeline : chaque étape entre la réception de l'entrée utilisateur et la livraison d'une réponse crée un point de fuite potentiel.

Nous avons cartographié chaque point de fuite à travers les systèmes IA que nous avons construits et déployés. Cet article en est le résultat. Pour la solution architecturale (tokenisation sémantique, frontières de confiance, restauration pilotée par des politiques), consulte notre guide de conformité RGPD. Cet article se concentre spécifiquement sur les endroits où les fuites se produisent et comment les détecter.

Les 9 points de fuite

Entrée utilisateur (contient des PII)
    │
    ├──▶ 1. PROMPTS ────────────▶ Le fournisseur LLM voit les données brutes
    │
    ├──▶ 2. EMBEDDINGS ─────────▶ La Vector DB stocke les PII de façon permanente
    │
    ├──▶ 3. LOGS ───────────────▶ L'agrégateur de logs indexe les PII
    │
    ├──▶ 4. APPELS D'OUTILS ────▶ Les API externes reçoivent les PII dans les paramètres
    │
    ├──▶ 5. MÉMOIRE D'AGENT ────▶ L'historique de conversation stocke les PII
    │
    ├──▶ 6. MESSAGES D'ERREUR ──▶ Le suivi d'erreurs capture les PII dans les stack traces
    │
    ├──▶ 7. CACHE ──────────────▶ Le cache de réponses stocke les PII dans les réponses mises en cache
    │
    ├──▶ 8. DONNÉES DE FINE-TUNING ▶ Les données d'entraînement contiennent des PII de façon permanente
    │
    └──▶ 9. TRANSFERTS D'AGENTS ▶ Les PII traversent les frontières de confiance entre agents

1. Prompts

Le point de fuite le plus évident et celui que la plupart des équipes pensent avoir résolu. Chaque prompt envoyé à un fournisseur LLM externe contient toutes les données que tu y mets. Si tu inclus le nom d'un client, son email, son historique de commandes ou le texte d'une réclamation dans le prompt, le fournisseur LLM les reçoit.

Où ça fuit :

  • L'API du fournisseur LLM reçoit le prompt complet
  • Le fournisseur peut journaliser les prompts pour la détection d'abus
  • Le fournisseur peut utiliser les prompts pour l'amélioration du modèle (selon les conditions d'utilisation et le niveau API vs consommateur)

Comment colmater : Remplace les PII brutes par des tokens sémantiques avant que le prompt n'atteigne le LLM. Le modèle reçoit {{person:p_001}} au lieu du vrai nom. Le token porte des métadonnées (genre, formalité, langue) pour que le modèle puisse quand même produire une sortie correcte.

// Avant : PII dans le prompt
const prompt = `Write a reply to Sara Mustermann about order #12345`;

// Après : prompt tokenisé
const transformed = await guardai.transform(prompt);
// transformed.safe_text = "Write a reply to {{person:p_001}} about order {{order:o_001}}"
const response = await llm.generate(transformed.safe_text);
const final = await guardai.rehydrate(response, transformed.session_state);

2. Embeddings

C'est le point de fuite que la plupart des équipes ratent complètement. Quand tu vectorises des documents pour le RAG, les vecteurs d'embedding encodent des informations sémantiques sur le contenu. Si le contenu contient des PII, les embeddings portent une représentation de ces PII dans le vector store.

Où ça fuit :

  • La base de données vectorielle stocke des embeddings dérivés de documents contenant des PII
  • La recherche par similarité peut faire remonter des PII à partir de requêtes non liées
  • Les sauvegardes de la base vectorielle contiennent des représentations de PII

Comment colmater :

Option A : Tokenise les documents avant la vectorisation. Les embeddings sont construits sur du texte tokenisé. Le vector store ne contient jamais de vecteurs dérivés de PII.

Option B : Vectorise les documents bruts mais tokenise au moment de la requête. Le vector store se trouve dans la zone de confiance. Seuls les chunks récupérés passent vers le LLM, et ceux-ci sont tokenisés avant de traverser la frontière.

// Option A : vectoriser du contenu tokenisé (plus sûr, qualité de récupération légèrement moindre)
const tokenized = await guardai.transform(documentText);
const embedding = await embedder.embed(tokenized.safe_text);
await vectorStore.upsert({ id: docId, embedding, metadata: { tokenized: true } });

// Option B : vectoriser brut, tokeniser au moment de la requête (meilleure récupération, plus complexe)
const embedding = await embedder.embed(documentText); // embedding brut
await vectorStore.upsert({ id: docId, embedding });
// Au moment de la requête : récupérer les chunks, puis tokeniser avant d'envoyer au LLM

Pour plus de détails sur l'architecture de pipelines RAG, consulte notre guide de fiabilité RAG et notre guide de recherche vectorielle.

3. Logs

Ton infrastructure de journalisation devient un dépôt de PII dès que tu journalises des prompts ou des réponses brutes. Ton cluster Datadog, CloudWatch, Elasticsearch ou Grafana Loki traite désormais des données personnelles, chacun nécessitant une documentation RGPD, des politiques de rétention et des procédures de droit d'accès.

Où ça fuit :

  • Les logs structurés contenant du texte de prompts
  • Le middleware de journalisation requête/réponse
  • Les logs de debug en développement qui atteignent la production
  • Les SDK de journalisation tiers qui capturent les corps de requête

Comment colmater : Journalise les identifiants de tokens, jamais les valeurs. Journalise les types d'événements, les compteurs d'entités, les scores de confiance et les noms de politiques. Ne journalise jamais le texte brut.

// Bien : log structuré sans PII
logger.info('transform_complete', {
    session_id: 'ses_abc',
    entities_detected: 3,
    entity_types: ['person', 'email', 'phone'],
    policy: 'german-support',
    duration_ms: 12,
});

// Mauvais : PII dans les logs
logger.info('Processing request', {
    input: 'Sara Mustermann wants to cancel order 12345...',
    // Ceci est maintenant du PII dans ton agrégateur de logs
});

4. Appels d'outils

Dans les systèmes agentiques, l'agent IA appelle des outils externes (API, bases de données, services). Les paramètres de l'appel d'outil contiennent souvent des PII extraites de la conversation. Un outil de recherche CRM reçoit un nom de client. Un outil de facturation reçoit un numéro de compte. Un outil d'email reçoit une adresse de destinataire.

Où ça fuit :

  • Les paramètres d'appels d'outils envoyés aux services externes
  • La journalisation des appels d'outils (les frameworks d'agents journalisent souvent chaque appel)
  • Les données de réponse des outils mises en cache dans la mémoire de l'agent

Comment colmater : Intercepte les appels d'outils à la frontière de confiance. L'agent passe des paramètres tokenisés. Le runtime résout les tokens en valeurs réelles à l'intérieur de la zone de confiance, appelle le service externe avec les données réelles, puis tokenise la réponse avant de la renvoyer à l'agent.

Agent : "Look up customer {{person:p_001}}"
  │
  ▼ (frontière de confiance)
Runtime : résout p_001 en "Sara Mustermann"
Runtime : appelle l'API CRM avec le vrai nom
Runtime : reçoit la réponse avec les données réelles
Runtime : tokenise la réponse
  │
  ▼
L'agent reçoit : "Customer {{person:p_001}}, account {{customer_id:cid_001}}"

L'agent ne voit et ne stocke jamais les valeurs brutes. Le service externe opère à l'intérieur de la zone de confiance. Pour voir comment nous implémentons cela dans le commerce agentique, consulte notre guide du commerce agentique.

5. Mémoire d'agent

Les systèmes IA agentiques maintiennent une mémoire de conversation entre les tours. Cette mémoire stocke l'intégralité de l'historique de conversation, y compris toutes les PII partagées par l'utilisateur. Si la mémoire est persistée (Redis, base de données), les PII s'accumulent au fil du temps.

Où ça fuit :

  • L'historique de conversation en mémoire pendant la session
  • La mémoire persistée dans les bases de données ou les key-value stores
  • La mémoire à long terme utilisée pour la personnalisation entre les sessions
  • La mémoire partagée entre agents dans les systèmes multi-agents

Comment colmater : Cadre la mémoire par tenant, session et thread. Tokenise les PII en mémoire de la même façon que tu tokenises les prompts. Définis des TTL sur la mémoire persistée. Ne partage jamais la mémoire entre les frontières de tenants.

// Cadrage de la mémoire : tenant + session + thread
const memoryKey = `${tenantId}:${sessionId}:${threadId}`;

// Le contenu de la mémoire est tokenisé
const memory = [
    { role: 'user', content: 'I am {{person:p_001}}, my order is {{order:o_001}}' },
    { role: 'assistant', content: 'Let me check order {{order:o_001}} for you, {{person:p_001}}.' },
];

// TTL : la mémoire expire après la fin de la session
await memoryStore.set(memoryKey, memory, { ttl: SESSION_TTL });

Pour les patterns d'isolation mémoire en multi-tenant, consulte notre guide de conception multi-tenant.

6. Messages d'erreur

Quand quelque chose échoue, les messages d'erreur et les stack traces contiennent souvent les données qui ont causé l'échec. Une erreur de parsing JSON inclut le JSON brut. Une erreur de validation inclut la valeur du champ invalide. Un timeout d'API inclut le payload de la requête.

Où ça fuit :

  • Les services de suivi d'erreurs (Sentry, Bugsnag, Datadog APM)
  • Les stack traces dans les réponses serveur
  • Les logs d'erreurs avec le contexte de requête
  • Les rapporteurs d'exceptions non gérées

Comment colmater : Nettoie les payloads d'erreur avant de les envoyer au suivi d'erreurs. Supprime les corps de requête du contexte d'erreur. Masque les PII dans les messages d'erreur. Ne renvoie jamais de détails d'erreur bruts aux clients.

// Middleware de nettoyage d'erreurs
function sanitizeError(error: Error, context: any): SanitizedError {
    return {
        message: error.message,
        code: error.code,
        // Supprime les PII du contexte
        context: {
            session_id: context.session_id,
            entity_types: context.entity_types,
            // NE PAS inclure : context.input, context.prompt, context.customerData
        },
    };
}

7. Cache

Le cache de réponses stocke la réponse complète, y compris toutes les PII dans la réponse générée. Si une réponse en cache contient "La commande de Sara Mustermann a été expédiée hier", chaque utilisateur suivant qui déclenche la même clé de cache voit les données de Sara.

Où ça fuit :

  • Les caches de réponses au niveau applicatif (Redis, Memcached)
  • Les caches CDN (si les réponses IA sont mises en cache en edge)
  • Les caches sémantiques (les questions similaires retournent des réponses mises en cache contenant des PII)

Comment colmater : Mets en cache les réponses tokenisées, pas les réponses réhydratées. Le cache stocke La commande de {{person:p_001}} a été expédiée hier. La requête de chaque utilisateur réhydrate avec son propre mapping de session.

Alternativement, inclus l'identifiant de session ou de tenant dans la clé de cache pour que les réponses personnalisées ne soient jamais servies au mauvais utilisateur.

8. Données de fine-tuning

Si tu fais du fine-tuning d'un modèle sur des données client, ces données sont intégrées de façon permanente dans les poids du modèle. Tu ne peux pas extraire des enregistrements spécifiques d'un modèle fine-tuné. Tu ne peux pas répondre à une demande de suppression RGPD pour des données qui ont été utilisées dans l'entraînement.

Où ça fuit :

  • Les datasets d'entraînement contenant des PII
  • Les poids du modèle (les données sont encodées, pas extractibles mais influencent les sorties)
  • Les données d'entraînement stockées par le fournisseur du modèle pendant le fine-tuning

Comment colmater : Tokenise les données d'entraînement avant le fine-tuning. Le modèle apprend des patterns à partir de texte tokenisé, pas à partir de PII réelles. Si tu dois utiliser des données réelles pour la qualité du fine-tuning, documente la base légale, implémente des politiques de rétention des données, et prépare-toi à ré-entraîner le modèle si une demande de suppression l'exige.

9. Transferts entre agents

Dans les systèmes multi-agents, un agent peut transférer une conversation à un autre agent. Le transfert inclut typiquement le contexte de conversation, qui contient des PII de l'interaction. Si les agents opèrent à travers différentes frontières de confiance (services différents, fournisseurs différents), les PII traversent ces frontières pendant le transfert.

Où ça fuit :

  • Les messages de transfert entre agents
  • Les dépôts de contexte partagés utilisés par plusieurs agents
  • Les appels API agent-à-agent transportant l'état de conversation
  • Les services d'orchestration qui routent entre agents

Comment colmater : Tokenise le contexte de transfert. L'agent receveur obtient un historique de conversation tokenisé, pas des PII brutes. Chaque agent opère dans le même modèle de frontière de confiance. Les transferts entre frontières passent par la même couche de tokenisation que tout autre franchissement de frontière de confiance.

Pour la façon dont nous concevons les architectures multi-agents avec une isolation correcte, ce guide couvre les patterns.

Le garde de sortie : attraper ce que le modèle invente

Au-delà des 9 points de fuite côté entrée, il y a un 10e problème : le modèle peut halluciner des PII qui n'étaient pas dans l'entrée originale. Si tu demandes au modèle d'écrire une réponse à {{person:p_001}}, il pourrait inventer un numéro de téléphone, une adresse ou un nom d'entreprise à partir de ses données d'entraînement.

Ces PII hallucinées ne sont pas protégées par ta tokenisation parce qu'elles n'ont jamais été tokenisées. La solution est une seconde passe de détection sur la sortie du modèle :

async function outputGuard(response: string, sessionTokens: Set<string>): GuardResult {
    // Lance la détection de PII sur la réponse du modèle
    const detected = await detector.detect(response);

    // Vérifie chaque entité détectée par rapport aux tokens de session connus
    const unknown = detected.filter(entity => !sessionTokens.has(entity.tokenId));

    if (unknown.length > 0) {
        return {
            safe: false,
            flagged: unknown,
            action: 'remove_or_flag', // Supprime les PII inconnues ou signale pour revue
        };
    }

    return { safe: true };
}

Le garde de sortie attrape : les numéros de téléphone inventés, les adresses hallucinées, les vrais noms d'entreprise issus des données d'entraînement, et toute autre PII que le modèle génère sans qu'elle soit dans l'entrée originale.

Pour plus de détails sur les modes de défaillance IA incluant l'hallucination, ce guide couvre les patterns plus larges.

Priorité de détection

Tous les points de fuite ne sont pas également dangereux. Priorise en fonction de la surface d'exposition et de la sensibilité des données :

PrioritéPoint de fuitePourquoi
P0PromptsVolume le plus élevé, PII directes vers le fournisseur externe
P0LogsSouvent négligés, créent un dépôt massif de PII
P1Appels d'outilsLes PII traversent vers plusieurs services externes
P1Mémoire d'agentLes PII s'accumulent au fil du temps
P1Messages d'erreurNon contrôlés, incluent souvent des payloads bruts
P2EmbeddingsExposition indirecte, mais permanente
P2CachePeut servir les données du mauvais utilisateur
P2Transferts d'agentsExposition inter-frontières
P3Données de fine-tuningExposition unique, mais irrécupérable

Commence par P0 (prompts et logs). Ce sont les plus volumineux et les plus faciles à corriger. Ensuite, traite P1 (appels d'outils, mémoire, erreurs). P2 et P3 sont importants mais moins urgents.

Pièges courants

  1. Penser que le chiffrement résout le problème. Le chiffrement protège le transit et le stockage. Il ne fait rien quand les données sont déchiffrées pour le traitement, ce qui est exactement ce que fait un LLM.

  2. Ne protéger que l'appel LLM final. Un workflow d'agent en 5 étapes a 5 surfaces de fuite. Protéger uniquement l'étape de génération laisse 4 étapes non protégées.

  3. Journaliser les prompts pour le debug. Chaque prompt que tu journalises est du PII dans ton agrégateur de logs. Journalise les identifiants de tokens, les types d'entités et les métadonnées à la place.

  4. Pas de garde de sortie. Le modèle hallucine des PII à partir des données d'entraînement. Sans une seconde passe de détection sur la sortie, les PII hallucinées atteignent l'utilisateur final.

  5. Mettre en cache les réponses réhydratées. Si le cache stocke "La commande de Sara Mustermann a été expédiée", tout utilisateur qui touche la même clé de cache voit les données de Sara.

  6. Faire du fine-tuning sur des données client brutes. Une fois que les PII sont dans les poids du modèle, elles ne peuvent être ni extraites ni supprimées. Tokenise les données d'entraînement.

  7. Ignorer le suivi d'erreurs. Sentry et Bugsnag capturent le contexte de requête par défaut. Ce contexte contient des PII si tes requêtes contiennent des PII.

  8. Mémoire d'agent partagée entre tenants. L'agent A d'un tenant ne doit pas avoir accès à la conversation de l'agent B d'un autre tenant.

Points clés à retenir

  • Les systèmes IA ont 9 points de fuite distincts. Prompts, embeddings, logs, appels d'outils, mémoire d'agent, messages d'erreur, cache, données de fine-tuning et transferts entre agents. Chacun nécessite sa propre stratégie de protection.

  • Le chiffrement n'aide pas au moment du traitement. Les données doivent être déchiffrées avant que le LLM puisse les traiter. La protection doit se faire au niveau de la couche applicative, pas au niveau de la couche de transport.

  • La tokenisation sémantique est la solution architecturale. Remplace les valeurs brutes par des tokens porteurs de métadonnées. Le LLM traite des tokens. Les valeurs réelles restent à l'intérieur de la zone de confiance.

  • Le garde de sortie attrape les PII hallucinées. Le modèle invente des données à partir de son jeu d'entraînement. Une seconde passe de détection sur la sortie attrape les entités qui n'étaient pas dans le mapping de tokens de la session.

  • Commence par les prompts et les logs (P0). Ce sont les plus volumineux et les plus faciles à corriger. Ensuite, traite les appels d'outils, la mémoire et les erreurs (P1).

  • Chaque point de fuite nécessite du monitoring. Suis combien d'entités PII sont détectées, combien sont tokenisées, combien passent entre les mailles. Alerte sur les anomalies.

Nous appliquons ces patterns à travers tous nos systèmes IA via OGuardAI, notre runtime open-source de protection sémantique des données. Si tu construis des systèmes IA qui traitent des données sensibles, contacte notre équipe ou demande un devis. Consulte nos services IA et notre page de confiance pour plus de contexte sur notre approche de la protection des données.

Sujets couverts

fuite de données IAexposition de données LLMPII dans les embeddingssécurité IAinjection de prompt donnéesprotection des données IAconfidentialité LLMprévention des fuites IA

Prêt à construire des systèmes IA prêts pour la production ?

Notre équipe est spécialisée dans les systèmes IA prêts pour la production. Discutons de comment nous pouvons aider.

Démarrer une conversation