Aller au contenu
Cercle IA Tech · RAG Un site du réseau Cercle IA Tech

Guide

RAG et droits d'accès : chacun ne voit que ses documents

Droits d'accès dans un RAG : filtrer à la recherche par groupes, pièges des bases partagées, exemples avec pgvector, Azure et LlamaIndex.

Mis à jour le

Dans un RAG d'entreprise, le contrôle d'accès se fait au moment de la recherche : chaque passage indexé porte la liste des groupes autorisés à le lire, et chaque recherche est filtrée sur les groupes de la personne qui pose la question. Le modèle ne reçoit ainsi jamais un passage interdit. Demander au modèle de « ne pas parler » d'un document qu'on lui a transmis n'est pas une protection.

Le risque, nommé par l'OWASP

L'OWASP (fondation qui publie des référentiels de sécurité applicative) consacre une entrée de son classement des risques des applications de modèles de langage aux faiblesses des vecteurs et plongements, LLM08:2025. Parmi les risques cités :

  • accès non autorisé et fuite de données, quand les contrôles d'accès sont insuffisants ou mal alignés ;
  • fuites d'informations entre contextes, dans les environnements où plusieurs catégories d'utilisateurs ou d'applications partagent la même base vectorielle ;
  • inversion des plongements, quand un attaquant reconstitue une partie du texte source à partir des vecteurs ;
  • empoisonnement des données, par des initiés ou des sources non vérifiées.

Parmi les parades recommandées : des bases vectorielles qui tiennent compte des permissions, avec un contrôle d'accès fin ; un partitionnement logique des données par niveau d'accès ; un étiquetage des données pour faire respecter ces niveaux ; et des journaux détaillés et infalsifiables des recherches.

Le principe : un filtre de sécurité à chaque recherche

Microsoft documente ce schéma pour Azure AI Search sous le nom de « security filter pattern » :

  1. chaque document indexé porte un champ group_ids (liste de groupes autorisés), filtrable et non renvoyé dans les résultats ;
  2. chaque requête applique le filtre group_ids/any(g:search.in(g, 'group_id1, group_id2')) avec les groupes de l'utilisateur ;
  3. seuls les documents dont un groupe correspond sont renvoyés.

Deux précisions de la documentation, valables au-delà d'Azure. D'abord, le champ de groupe n'est qu'une chaîne : il n'y a ni authentification ni autorisation dans le filtre lui-même. C'est votre application qui doit établir, de façon sûre, à quels groupes appartient l'utilisateur. Ensuite, masquer le champ dans les résultats ne protège rien : c'est l'application du filtre à chaque requête qui fait la sécurité. Microsoft signale aussi qu'Azure AI Search propose une prise en charge intégrée des listes de contrôle d'accès au niveau du document, pour les cas où elle est utilisable.

Avec PostgreSQL et pgvector

Avec pgvector, le filtre est une clause WHERE ordinaire combinée à la recherche par distance :

SELECT * FROM items WHERE category_id = 123 ORDER BY embedding <-> '[3,1,2]' LIMIT 5;

Remplacez category_id par une colonne de groupes. Point d'attention signalé par la documentation : avec un index approximatif, le filtre s'applique après le parcours de l'index, et la requête peut renvoyer moins de résultats que demandé. Depuis la version 0.8.0, les parcours itératifs (SET hnsw.iterative_scan = strict_order;) parcourent davantage l'index jusqu'à trouver assez de résultats.

Avec LlamaIndex

LlamaIndex permet de filtrer les passages par métadonnées avant la recherche des plus proches, avec des filtres du type ExactMatchFilter, transmis au moteur de requête par filters=. Le principe reste le même : la métadonnée est posée à l'indexation, le filtre est imposé par votre code, jamais choisi par le modèle.

Les pièges courants

Piège Conséquence Parade
Droits copiés une fois à l'indexation un départ ou un changement de poste n'est pas répercuté resynchroniser les droits avec l'annuaire
Filtre choisi par le modèle une question habile, ou un document piégé, peut l'élargir filtre posé par le code, à partir de l'identité authentifiée
Cache des réponses partagé une réponse calculée pour un directeur servie à un stagiaire clé de cache incluant les groupes
Résumés ou index dérivés (graphe, résumés de communautés) ils mélangent des documents de niveaux différents un index dérivé par niveau d'accès, ou pas d'index dérivé
Journaux trop bavards les passages confidentiels se retrouvent dans les journaux journaliser les identifiants, pas les textes

Exemple illustratif

Prenons une entreprise industrielle de quatre-vingts personnes avec trois niveaux : documents ouverts à tous (procédures, sécurité), documents de service (qualité, achats), documents de direction (contrats, comptes, stratégie). À l'indexation, chaque passage reçoit la liste des groupes de son dossier d'origine. À la question, l'application lit les groupes de l'utilisateur dans l'annuaire, les ajoute au filtre, et le modèle ne voit que ce que la personne pourrait ouvrir elle-même dans le partage de fichiers.

Et les données personnelles

Si vos documents contiennent des données personnelles, leur indexation pose aussi des questions relevant du règlement général sur la protection des données (RGPD). Cette page décrit une technique, pas un avis juridique : faites examiner votre projet par votre délégué à la protection des données ou par un professionnel du droit.

Questions fréquentes

Peut-on demander au modèle de ne pas révéler certains documents ?

Ce n'est pas une protection fiable. Le filtrage doit se faire à la recherche : un passage que l'utilisateur n'a pas le droit de lire ne doit jamais être transmis au modèle.

Avec pgvector, un filtre WHERE peut-il faire perdre des résultats ?

Oui : avec un index approximatif, le filtre s'applique après le parcours de l'index, et la requête peut renvoyer moins de lignes que demandé. Les parcours itératifs, disponibles depuis la version 0.8.0, corrigent ce point.

Sources

Pages consultées pour écrire cet article :

  1. https://genai.owasp.org/llmrisk/llm082025-vector-and-embedding-weaknesses/
  2. https://learn.microsoft.com/en-us/azure/search/search-security-trimming-for-azure-search
  3. https://github.com/pgvector/pgvector
  4. https://developers.llamaindex.ai/python/framework/optimizing/basic_strategies/basic_strategies/

À lire aussi