Zurück
Kevin Riedl

14 min Lesezeit · 11. Juni 2026

Weiter

RAG über SharePoint, Confluence und Google Drive: Permissions-First-Architektur

Das harte Problem in Enterprise-RAG ist nicht die Retrieval-Qualität, es sind die Berechtigungen: Der Assistent darf niemals ein Dokument an Nutzer ausspielen, die es nicht sehen dürfen. Das Embedding entfernt die Access Control List, sodass eine naive Pipeline nach dem Muster "alles embedden, Top-k abrufen" auf Ähnlichkeit statt auf Autorisierung matcht und so Daten leakt. Die Lösung ist architektonisch. Erzwinge den Zugriff auf der Retrieval-Ebene, nicht im Prompt: Häng die ACL jedes Quelldokuments als versioniertes, filterbares Metadatum an jeden Chunk und filtere die Vektorsuche vor dem Retrieval nach Identität und Gruppenzugehörigkeiten des anfragenden Nutzers, sodass das Modell nur autorisierte Chunks zu sehen bekommt. Gib die Identität des Endnutzers weiter, nicht die eines Service-Accounts; speichere Gruppen-IDs, nicht Nutzer-IDs; lass Deny vor Grant gewinnen; und halte die ACLs aktuell, denn eine entzogene Berechtigung, die der Index noch nicht nachvollzogen hat, ist ein aktives Leak.

Dies ist der Implementierungs-Begleiter zu unserer RAG-Production-Readiness-Checkliste, die Per-User-Berechtigungen als das harte Sicherheitsproblem benennt. Dieser Beitrag zeigt, wie du es tatsächlich löst. Anbieterspezifische und Preview-Funktionen ändern sich schnell; prüf die verlinkten Docs erneut, bevor du baust.

Baust du einen RAG-Assistenten über deinen Dokumentenspeichern?

 Kostenloses Beratungsgespräch buchen

Warum Berechtigungen der schwierige Teil sind

Das Fehlerszenario in einem Satz: Das Modell formuliert eine flüssige Antwort, die auf einem Dokument basiert, das der anfragende Nutzer nie sehen durfte, weil das Retrieval auf semantische Ähnlichkeit gematcht hat und nicht auf Autorisierung. Sobald ein Dokument gechunkt und in einen gemeinsamen Index embedded ist, wandern die Eigentümer, Zugriffsstufen und Sensitivitätskennzeichnungen des Quellsystems nicht mit dem Vektor mit, sofern du sie nicht bewusst mitführst. Ein Vektorspeicher hat kein Konzept davon, wer fragt.

Microsoft 365 Copilot ist der kanonische Praxisfall. Es bricht Berechtigungen nicht, es respektiert sie. Das Problem ist, dass es Inhalte, die bereits übermäßig geteilt, aber schwer auffindbar waren, trivial auffindbar macht, sodass latentes Over-Permissioning, das niemandem aufgefallen ist, zu einer Ein-Prompt-Anfrage wird. Microsofts eigene Gegenmaßnahmen sind aufschlussreich: Werkzeuge, die riskante Inhalte aus der Reichweite des Assistenten herausziehen (Restricted Content Discovery, Data-Access-Governance-Reports), statt das Modell zu bitten, sich zu benehmen.

Was der entscheidende Punkt ist: Dem Modell zu sagen, ein Dokument nicht preiszugeben, ist keine Kontrolle. Die OWASP-Leitlinie zu Sensitive Information Disclosure stellt klar fest, dass System-Prompt-Restriktionen möglicherweise nicht eingehalten werden und durch Prompt Injection umgangen werden können. Prompt Injection ist das LLM-Risiko Nummer eins, und es kann indirekt eintreffen, versteckt in einem abgerufenen Dokument. Forscher haben eine nahezu vollständige Umgehung von Produktions-Guardrails demonstriert, und eine Prompt-Injection-Kette in Copilots Enterprise-Suche aus dem Jahr 2026 funktionierte genau deshalb, weil ein Leak-Prevention-Schutz nur für die erste Anfrage galt. Die Grenze muss die Architektur sein, nicht der Prompt.

Das Prinzip: auf der Retrieval-Ebene durchsetzen

Der Vektorspeicher darf ein unautorisiertes Dokument gar nicht erst zurückgeben, und das Modell darf es nie verarbeiten. Das erreichst du, indem du jeden Chunk zur Index-Zeit mit normalisierten, versionierten ACL-Metadaten taggst und zur Retrieval-Zeit einen Berechtigungsfilter in die Query einbaust. Das Filtern nach dem Retrieval, auf der Anwendungsebene oder im Prompt, scheitert auf zwei Wegen: Es verschwendet das Kontextfenster, indem es Dokumente abruft, nur um sie wieder zu verwerfen, und wenn die App-Logik einen Bug hat oder durch eine Injection umgangen wird, fließen die Dokumente trotzdem durch. Post-Filtering bricht außerdem leise den Recall, denn das Herausstreichen unautorisierter Chunks aus einem Top-k-Set kann dem Modell nichts mehr lassen, wenn die autorisierten Ergebnisse knapp außerhalb von k lagen. Filtere bereits bei der Suche vor, oder ruf ein Vielfaches von k ab und filtere dann.

Berechtigungsmodelle pro Quelle

Jede Quelle hat ihr eigenes ACL-Modell und ihre eigenen Fallen. Du ingestierst mit einer erhöhten Identität, die alle Inhalte und deren Berechtigungen lesen kann, normalisierst jede Quelle auf dieselbe Form und löst auf Gruppen-IDs auf.

QuelleWie Berechtigungen funktionierenDie Falle, die du behandeln musst
SharePoint / OneDrive (Microsoft Graph)Berechtigungen kaskadieren von der Site zur Bibliothek zum Element; ACLs über den Item-Permissions-Endpoint mit grantedToV2 auslesenDas Teilen einer einzelnen Datei bricht still die Vererbung; "Limited Access" ist Infrastruktur, kein Lesezugriff; Sensitivitätskennzeichnungen fügen eine zweite Schranke hinzu (der Nutzer braucht die Rechte EXTRACT und VIEW, nicht nur die SharePoint-ACL)
ConfluenceDer effektive Lesezugriff ist die Schnittmenge aus Space-Berechtigung und Page-Restriction; View-Restrictions vererben sich auf UnterseitenDie Cloud-Restrictions-API liefert vererbte Restrictions nicht zurück, daher musst du jeden Vorfahren durchlaufen und deren Lese-Restrictions vereinigen, sonst leakst du eingeschränkte Unterseiten
Google DriveSechs Rollen, Grantee-Typen user/group/domain/anyone; ACLs über die Permissions-Liste mit permissionDetails für die Vererbung auslesenShared Drives sind strikt expansiv (ein Kind kann nicht weniger Zugriff haben als sein Parent); eine Berechtigungsänderung am Parent erzeugt keinen Change-Log-Eintrag am Kind, daher musst du neu propagieren

Ein Detail, das Teams beißt: Programmiere gegen Microsoft Graph gegen grantedToV2 und grantedToIdentitiesV2; die älteren grantedTo-Felder sind deprecated. Und die Sichtbarkeit von Berechtigungen ist selbst access-trimmed, daher braucht ein vollständiger ACL-Crawl eine Application Identity mit den richtigen Read-All-Scopes, kein delegiertes Nutzertoken.

Implementierungsmuster, die halten

  • Speichere Gruppen-IDs am Chunk, nicht Nutzer-IDs. Geringere Kardinalität, und eine Mitgliedschaftsänderung braucht keine Neuindexierung, nur eine Gruppenauflösung zur Query-Zeit. Löse transitive, verschachtelte Mitgliedschaft auf der Principal-Seite auf.
  • Ruf mit der Identität des Endnutzers ab. Ingestiere mit einer Service-Identität, aber filtere zur Query-Zeit mit der Identität und den Group-Claims des Endnutzers, weitergegeben über OAuth on-behalf-of. Verwende die unveränderliche Object-ID und die Group-Object-IDs für die Autorisierung, niemals einen veränderlichen Anzeigenamen. On-behalf-of funktioniert nur für Nutzer, nicht für Service Principals, daher kann eine reine Service-Account-Kette kein Per-User-Trimming leisten.
  • Filtere an der ANN-Query mit einem Set-Membership-Test vor. Verwende eine Set-Funktion (im Äquivalent deines Vektorspeichers zu search.in oder einem $in-Filter) über die erlaubten Principals des Nutzers; eine lange Kette aus Gleichheits-ORs ist Sekunden langsamer. Deny gewinnt vor Grant.
  • Behandle das Entra-Groups-Overage. Ist ein Nutzer in mehr als etwa 200 Gruppen, lässt das Identity-Token den Groups-Claim fallen und gibt einen Overage-Pointer aus; die Retrieval-Ebene muss das erkennen und die vollständige Liste nachladen, sonst werden Nutzer mit hoher Gruppenanzahl still under-filtered.
  • pgvector mit Postgres Row-Level Security ist ein sauberes Primitiv: Eine Select-Policy hängt an jede Query, inklusive der Ähnlichkeitssuche, ein Berechtigungsprädikat an, sodass es im App-Code unmöglich zu umgehen ist. Achte auf die Latenz, denn die Policy kann mit dem approximativen Index in Konflikt geraten; mildere das mit partiellen Per-Tenant-Indizes oder Partitionierung und setze die Identity-Variable pro Request in deinem Connection-Pooler.

Es gibt eine echte Gabelung in den Empfehlungen, die man benennen sollte. Ein Lager (darunter AWS) argumentiert, dass Metadatenfilterung zur Query-Zeit allein nicht ausreicht und du die Autorisierung beim Retrieval erneut gegen die Quelle prüfen solltest, weil synchronisierte Metadaten veralten. Das andere (darunter Microsofts Referenzmuster) synchronisiert ACLs in den Index und setzt sie zur Query-Zeit mit dem Token des Nutzers durch, des Durchsatzes wegen. Es ist ein echter Trade-off: Aktualität gegen Latenz. Wähl nach der Sensibilität der Daten.

Das Aktualitätsproblem, das niemand einplant

Wenn Berechtigungen beim Ingest materialisiert werden, wird ein quellseitiger Entzug nicht automatisch propagiert, sodass ein Nutzer, dem der Zugriff entzogen wurde, ein Dokument im Index bis zur nächsten Synchronisation weiterhin sehen kann. Es gibt zwei Leak-Fenster: das Sync-Fenster zwischen einer Quelländerung und dem Index-Update sowie der Blindspot beim vererbten Scope, bei dem ein Werkzeug ACLs auf Elementen mit eindeutigen Berechtigungen aktualisiert, aber Änderungen verpasst, die aus einem Parent-Scope kamen. SharePoint braucht einen expliziten Permissions-Resync für vererbte Änderungen; Parent-Änderungen an Google Drives Shared Drives hinterlassen keinen Change-Log-Eintrag am Kind. Nutze die Change-Feeds der Quelle (Google Drives Changes-API feuert bei Berechtigungsänderungen, nicht nur bei Edits) und materialisiere entweder schneller mit Webhooks oder führe eine Live-Last-Mile-Prüfung durch, gemäß der obigen Gabelung.

Löschung ist die andere Hälfte. Das Recht auf Vergessenwerden bedeutet, auf jeder Ebene zu löschen: das Quellobjekt, jeden abgeleiteten Chunk und jedes Embedding, samt Caches. Entwirf die Chunk-IDs von Anfang an so, dass das Löschen eines Dokuments und all seiner Chunks eine günstige Operation ist. Und behandle das Embedding selbst als personenbezogene Daten: Forschung zu Embedding-Inversion hat den Großteil kurzer Quelltexte allein aus dem Vektor rekonstruiert, sodass ein Löschen, das das Embedding zurücklässt, in Wahrheit nichts vergessen hat.

DSGVO und Datenresidenz

Permissions-First-RAG bildet die DSGVO sauber ab. Datenminimierung spricht gegen das Bulk-Vektorisieren von allem Erreichbaren; ruf nur ab und embedde nur, was der Assistent braucht. Dem Rechenschaftsprinzip dient am besten ein konkretes Artefakt: ein Per-Query-Retrieval-Audit-Log, das festhält, welche Dokumente welcher Identität für welche Query ausgespielt wurden, was dir zudem erlaubt, einen vermuteten Stale-ACL-Leak im Nachhinein zu untersuchen. Und wo die Daten liegen, ist weiterhin wichtig, also route die Inferenz in eine EU-Region und schließe einen Auftragsverarbeitungsvertrag mit dem Modellanbieter, was wir in EU-Datenresidenz für KI-Apps im Jahr 2026 behandeln.

Die Referenzarchitektur, und die Anti-Pattern

End-to-End: Ingestiere jede Quelle mit einer Identität, die alle Inhalte und ACLs lesen kann; extrahiere die effektive ACL pro Element (unter Beachtung gebrochener Vererbung, Durchlaufen der Confluence-Vorfahren, Lesen der Drive-Vererbung); chunke, embedde und häng die normalisierte versionierte ACL als filterbares Metadatum an jeden Chunk; ruf mit der Endnutzer-Identität und einem verpflichtenden Berechtigungsfilter ab; generiere nur aus autorisierten Chunks; logge jede Entscheidung; und betreibe eine Aktualitäts-Schleife aus den Change-Feeds der Quelle mit explizitem Resync für vererbte Änderungen und kaskadierenden Löschungen bis zu Chunks und Embeddings.

Die Anti-Pattern, von denen die meisten reale Vorfälle sind, die nur darauf warten zu passieren: ein gemeinsamer Index ohne Berechtigungsfilter; Filtern nach dem Retrieval oder im Prompt; dem Modell zu vertrauen, dass es sich selbst zensiert; mit einer Service-Account-Identität abzurufen, was das Per-User-Trimming aushebelt; Per-User-IDs statt Gruppen-IDs zu speichern; SharePoints "Limited Access" als Lesezugriff zu behandeln; Confluence-Restrictions ohne Durchlaufen der Vorfahren zu lesen; nur SharePoint-ACLs zu spiegeln und dabei die Label-Verschlüsselung zu ignorieren; nur bei vollständigen Crawls zu aktualisieren, sodass Entzüge nachhängen; und das Quelldokument zu löschen, aber das Embedding zurückzulassen.

Kevin Riedl

"Das Modell ist nicht deine Zugriffskontrolle, und der Prompt ist nicht deine Sicherheitsgrenze. Wenn ein Nutzer ein Dokument nicht lesen darf, darf der Vektorspeicher es nie zurückgeben. Alles andere, die Labels, die Aktualität, das Audit-Log, steht im Dienst dieser einen Regel."

Häufig gestellte Fragen

Wie setzt du Berechtigungen in RAG durch?
Häng die ACL jedes Quelldokuments (erlaubte Nutzer und Gruppen) zur Index-Zeit als versioniertes, filterbares Metadatum an jeden Chunk und filtere die Vektorsuche dann vor dem Retrieval nach Identität und Gruppenzugehörigkeiten des anfragenden Nutzers. Das Modell sieht nur autorisierte Chunks. Setz es niemals im Prompt oder nach dem Retrieval durch.
Respektiert RAG SharePoint-Berechtigungen?
Nicht standardmäßig, denn das Embedding entfernt die ACL. RAG respektiert sie nur, wenn du die SharePoint- und Graph-Berechtigungen (mit grantedToV2, gebrochener Vererbung sowie den EXTRACT- und VIEW-Rechten der Sensitivitätskennzeichnung) zusammen mit dem Inhalt ingestierst und zur Query-Zeit mit der Identität des angemeldeten Nutzers Security-Trimming betreibst. Microsoft 365 Copilot macht das nativ.
Was ist Security Trimming in RAG?
Das Entfernen von Ergebnissen, die der aktuelle Nutzer nicht sehen darf. Early-Binding-Security-Trimming wendet das Set erlaubter Principals des Nutzers als verpflichtenden Filter an der Suche an, sodass unautorisierte Dokumente nie zurückgegeben werden, im Gegensatz zum Post-Filtering, das erst abruft und dann verwirft und sowohl langsamer als auch leak-anfällig ist.
Wie implementierst du Per-User-Berechtigungen in RAG?
Ingestiere mit einer Service-Identität, aber ruf mit der Identität des Endnutzers über OAuth on-behalf-of ab, unter Verwendung der unveränderlichen Object-ID und der Group-Claims. Speichere Gruppen-IDs an den Chunks, löse den Nutzer zur Query-Zeit auf Gruppen auf, filtere die Vektorsuche vor und lass Deny vor Grant gewinnen.
Soll ich Nutzer-IDs oder Gruppen-IDs an jedem Chunk speichern?
Gruppen-IDs. Diese haben eine geringere Kardinalität, und eine Mitgliedschaftsänderung braucht keine Neuindexierung, nur eine Gruppenauflösung zur Query-Zeit. Löse transitive, verschachtelte Gruppenmitgliedschaft zur Query-Zeit auf der Principal-Seite auf.
Wie halte ich Berechtigungen aktuell, damit ich nach einem Entzug nicht leake?
Nutze Change-Feeds der Quelle (Google Drives Changes-API, SharePoint-Delta plus Indexer, Confluence-Polling) für inkrementellen ACL-Sync und synchronisiere vererbte oder Parent-Scope-Änderungen explizit nach, den üblichen Blindspot. Materialisiere entweder schneller mit Webhooks oder führe zur Query-Zeit eine Live-Last-Mile-Autorisierungsprüfung durch.
Kann ich dem Modell nicht einfach sagen, eingeschränkte Dokumente nicht preiszugeben?
Nein. OWASP stellt fest, dass System-Prompt-Restriktionen möglicherweise nicht eingehalten werden und durch Prompt Injection umgangen werden können, und Forscher haben eine nahezu vollständige Umgehung von Produktions-Guardrails gezeigt. Zugriffskontrolle muss architektonisch sein, auf der Retrieval-Ebene.
Kann pgvector Per-User-Zugriff durchsetzen?
Ja. Postgres Row-Level Security fügt jeder Query, inklusive der Ähnlichkeits-Query, ein Berechtigungsprädikat hinzu, sodass es im App-Code unmöglich zu umgehen ist. Injiziere die Identität über eine Session-Variable. Achte auf die Latenz, denn die Policy kann mit dem approximativen Index in Konflikt geraten; mildere das mit partiellen Per-Tenant-Indizes oder Partitionierung.
Sind Dokument-Embeddings personenbezogene Daten unter der DSGVO?
Behandle sie als solche. Embedding-Inversion-Angriffe rekonstruieren den Großteil kurzer Quelltexte allein aus dem Vektor, sodass ein Embedding die betroffene Person identifizieren kann. Das Recht auf Vergessenwerden erfordert daher auch das Löschen des Embeddings, nicht nur des Quelldokuments.
Wie unterscheidet sich die Confluence-Berechtigungs-Ingestion?
Der effektive Lesezugriff ist die Schnittmenge aus Space-Berechtigung und Page-Restriction, und View-Restrictions vererben sich auf Unterseiten. Die Cloud-Restrictions-API liefert vererbte Restrictions nicht zurück, daher musst du die Vorfahren durchlaufen und deren Lese-Restrictions vereinigen, sonst leakst du eingeschränkte Unterseiten.

Fazit

Enterprise-RAG über deinen eigenen Dokumentenspeichern steht und fällt mit einer Regel: Wenn ein Nutzer ein Dokument nicht lesen darf, darf der Retriever es nie zurückgeben, und das Modell darf es nie sehen. Das Embedding entfernt die ACL, dem Prompt kann man nicht zutrauen, sie wieder einzusetzen, und das Leak-Fenster nach einem Entzug ist real.

Bau also Permissions-First. Trag die ACL jeder Quelle als versioniertes Metadatum auf jeden Chunk, ruf mit der Identität des Endnutzers und einem verpflichtenden Filter ab, halte die ACLs aus den Change-Feeds der Quelle aktuell, behandle das Embedding als personenbezogene Daten und logge, was der Assistent wem gezeigt hat. Bring diese Architektur in Ordnung, und der Rest von RAG ist der einfache Teil.

Möchtest du ein Permissions-First-RAG auf deinem SharePoint, Confluence oder Drive?

 Kostenloses Beratungsgespräch buchen
Zurück
Kevin Riedl

14 min Lesezeit · 11. Juni 2026

Weiter

Hilfe für KI in Produktion

Du baust ein KI-Produkt und machst dir Sorgen um Inference-Kosten, Architektur oder Production Readiness? Wavect hilft Gründern, KI-Prototypen in zuverlässige Produktionssysteme zu verwandeln.

Passender Service: