Pourquoi ce sujet est important
Un RAG donne au modèle accès à des documents qui peuvent être confidentiels, obsolètes ou malveillants. La sécurité ne se résume donc pas au chiffrement de la base vectorielle : elle doit couvrir l’ingestion, les droits, la récupération, le prompt, les outils et les traces.
Cartographier les actifs
Listez sources, fichiers, texte extrait, fragments, embeddings, métadonnées, index, cache, prompts et traces. Classez les documents et identifiez propriétaire, tenant, durée et groupes autorisés. Sans métadonnées fiables, une autorisation fine devient impossible.
Sécuriser l’ingestion
Validez type, taille et structure des fichiers. Analysez malware, secrets, PII et contenu interdit. Extrayez dans un environnement isolé lorsque les formats sont complexes. Conservez provenance, hash et version du parseur. Un document importé ne doit pas devenir immédiatement consultable sans politique définie.
Appliquer les autorisations
L’autorisation doit être calculée par le backend à partir de l’identité authentifiée. Le modèle ne choisit jamais le tenant ni les groupes autorisés. Appliquez les filtres avant ou pendant la recherche vectorielle, puis vérifiez les résultats avant de construire le contexte. Testez les frontières entre tenants.
Résister aux injections
Un document peut contenir “ignore les instructions” ou demander l’exfiltration d’un secret. Traitez le contenu récupéré comme une donnée non fiable, séparez instructions et documents, limitez les outils et exigez une confirmation pour les actions sensibles. Les règles d’autorisation restent hors du modèle.
Chiffrer et limiter les accès
Utilisez TLS, chiffrement du stockage et gestion centralisée des clés. Séparez comptes d’ingestion, lecture et administration. Restreignez réseau, sauvegardes et consoles. La rotation des clés et la restauration doivent être testées.
Supprimer réellement
La suppression d’un document doit retirer original, texte, fragments, embeddings, cache et copies de test selon la politique. Utilisez un identifiant de provenance stable et un workflow idempotent. Documentez le délai des sauvegardes.
Tableau de décision
| Étape | Menace | Contrôle |
|---|---|---|
| Upload | Malware, format piégé | Validation et sandbox |
| Extraction | Secrets, PII | Détection et minimisation |
| Index | Mélange de tenants | Métadonnées et filtres |
| Retrieval | Contournement des droits | Autorisation serveur |
| Prompt | Injection documentaire | Séparation et outils bornés |
| Logs | Fuite secondaire | Redaction et rétention |
Exemple concret
Dans un RAG juridique multi-clients, chaque fragment possède client_id, dossier_id et groupes. L’API dérive ces valeurs du jeton utilisateur et construit elle-même le filtre Qdrant ou Weaviate. Les résultats sont revérifiés avant le LLM. Un document supprimé déclenche une tâche qui efface toutes ses dérivées et produit une preuve d’exécution.
Les erreurs fréquentes
- laisser le frontend fournir librement le tenant_id
- croire qu’un embedding est anonyme
- donner au modèle le pouvoir de décider des droits
- indexer immédiatement tout fichier importé
- enregistrer documents et prompts dans les traces
- oublier caches, sauvegardes et environnements de test
Checklist de mise en production
- [ ] Inventaire des copies de données
- [ ] Validation et analyse des fichiers
- [ ] Métadonnées de provenance obligatoires
- [ ] Filtres d’autorisation côté serveur
- [ ] Tests croisés entre tenants
- [ ] Outils du modèle limités
- [ ] Logs minimisés
- [ ] Suppression de bout en bout testée
FAQ
Les embeddings peuvent-ils révéler le texte ?
Ils ne doivent pas être considérés comme anonymes. Protégez-les selon la sensibilité des données sources.
Le filtrage après la recherche suffit-il ?
Il peut déjà exposer scores ou contenus au service. Appliquez le contrôle le plus tôt possible et revérifiez avant le contexte.
Comment tester une prompt injection ?
Ajoutez des documents malveillants à un environnement de test et vérifiez que le modèle ne change pas de règles ni n’appelle un outil interdit.
Faut-il une base par client ?
Pas toujours. L’isolation logique peut suffire selon le risque, mais une séparation physique peut être justifiée pour des clients sensibles.
Exemple : filtrage par tenant obligatoire
La séparation doit être imposée par le code, pas demandée au modèle. Avec Qdrant, injectez le tenant depuis l’identité authentifiée :
from qdrant_client.models import Filter, FieldCondition, MatchValue
def search_for_user(client, collection, vector, identity):
if not identity.tenant_id:
raise PermissionError("tenant manquant")
return client.search(
collection_name=collection,
query_vector=vector,
query_filter=Filter(must=[
FieldCondition(
key="tenant_id",
match=MatchValue(value=identity.tenant_id),
)
]),
limit=8,
with_payload=["title", "excerpt", "source_id"],
)Appliquez le même contrôle à l’ingestion, à la recherche et à l’accès au document source. Chiffrez les sauvegardes et les flux réseau, mais gardez à l’esprit que le chiffrement ne remplace pas l’autorisation. Évitez de stocker le texte intégral dans les logs ou les traces LLM. Pour vérifier l’isolation, créez deux tenants de test, indexez un marqueur unique dans chacun et affirmez qu’aucune requête croisée ne le retourne.