[{"data":1,"prerenderedAt":661},["ShallowReactive",2],{"blog-rag-access-control-permissions-de":3},{"slug":4,"published":5,"minutes":6,"category":7,"tags":8,"keywords":14,"about":27,"sources":37,"cover":62,"og":63,"expertise":64,"locales":65,"lang":67,"title":69,"description":70,"coverAlt":71,"metaTitle":72,"takeaways":73,"faq":79,"toc":95,"blocks":126,"others":423},"rag-access-control-permissions","2026-10-17",9,"rag",[9,10,11,12,13],"RAG","Access control","Security","Multi-tenancy","Vector search",[15,16,17,18,19,20,21,22,23,24,25,26],"rag access control","permission aware rag","document level security rag","rag multi tenancy","vector database access control","pgvector row level security","security trimming azure ai search","openfga rag authorization","qdrant multitenancy","pinecone namespaces multitenancy","owasp llm08 vector and embedding weaknesses","rag data leakage",[28,31,34],{"name":29,"url":30},"Access-control list","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FAccess-control_list",{"name":32,"url":33},"Multitenancy","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FMultitenancy",{"name":35,"url":36},"Retrieval-augmented generation","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FRetrieval-augmented_generation",[38,41,44,47,50,53,56,59],{"title":39,"url":40},"OWASP GenAI Security Project: LLM08:2025 Vector and Embedding Weaknesses","https:\u002F\u002Fgenai.owasp.org\u002Fllmrisk\u002Fllm082025-vector-and-embedding-weaknesses\u002F",{"title":42,"url":43},"PostgreSQL documentation: Row Security Policies","https:\u002F\u002Fwww.postgresql.org\u002Fdocs\u002Fcurrent\u002Fddl-rowsecurity.html",{"title":45,"url":46},"pgvector README: filtering and iterative index scans","https:\u002F\u002Fgithub.com\u002Fpgvector\u002Fpgvector",{"title":48,"url":49},"Qdrant: Multitenancy and partitions guide","https:\u002F\u002Fqdrant.tech\u002Fdocumentation\u002Fguides\u002Fmultiple-partitions\u002F",{"title":51,"url":52},"Pinecone: Implement multitenancy using namespaces","https:\u002F\u002Fdocs.pinecone.io\u002Fguides\u002Findex-data\u002Fimplement-multitenancy",{"title":54,"url":55},"Microsoft Learn: Document-level access control in Azure AI Search","https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fazure\u002Fsearch\u002Fsearch-document-level-access-overview",{"title":57,"url":58},"OpenFGA: RAG authorization use case","https:\u002F\u002Fopenfga.dev\u002Fdocs\u002Fuse-cases\u002Frag-authorization",{"title":60,"url":61},"Morris et al.: Text Embeddings Reveal (Almost) As Much As Text (EMNLP 2023)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2310.06816","\u002Fimages\u002Fblog\u002Frag-access-control-permissions\u002Fcover.webp","\u002Fimages\u002Fblog\u002Frag-access-control-permissions\u002Fog.jpg","ai-engineer",[66,67,68],"en","de","hu","Zugriffskontrolle für RAG: berechtigungsbewusstes Retrieval ohne Datenlecks","Wie RAG-Assistenten Dokumente preisgeben und wie man das stoppt: ACLs an jedem Chunk, Vorfilter, Row-Level Security in pgvector, Rechte-Sync und Lecktests.","Sieben Karten in einer Reihe, sechs mit Schloss, eine leere Karte schickt einen Pfeil nach außen.","Zugriffskontrolle für RAG · Balázs Csorba",[74,75,76,77,78],"Berechtigungen in der Retrieval-Abfrage durchsetzen, bevor Text das Modell erreicht; ein System-Prompt ist keine Zugriffskontrolle.","Jeder Chunk erbt die ACL seines Quelldokuments, idealerweise als Gruppen-IDs, dazu eine Mandanten-ID und den Zeitpunkt der letzten ACL-Synchronisierung.","Gefilterte Vektorsuche hat eine Recall-Falle: pgvector wendet den Filter nach dem HNSW-Scan an, ein 10-%-Filter kann so etwa 4 Treffer übrig lassen, wenn iterative Scans nicht aktiv sind.","Rechteänderungen wirken erst, wenn sie den Index erreichen; ACLs daher getrennt vom Inhalt synchronisieren und Quellen mit hohem Risiko bei der Anfrage prüfen.","Caches, Zusammenfassungen, Gedächtnis und Embeddings sind abgeleitete Daten und brauchen dieselben Rechte wie ihre Quelldokumente.",[80,83,86,89,92],{"q":81,"a":82},"Was ist berechtigungsbewusstes RAG?","Ein RAG-System, das nur Chunks abruft, die der anfragende Nutzer im Quellsystem lesen darf. Die Identität des Nutzers wird zu Gruppen aufgelöst, und diese Gruppen filtern die Suche, bevor Text an das Modell geht.",{"q":84,"a":85},"Soll ich vor oder nach der Vektorsuche filtern?","Davor, wann immer der Speicher es unterstützt. Ein Vorfilter in der Abfrage hält nicht berechtigte Chunks ganz aus der Kandidatenmenge. Nachfiltern mit einem Autorisierungsdienst funktioniert auch, man muss aber mehr abrufen und riskiert leere Ergebnisseiten.",{"q":87,"a":88},"Ist ein Index pro Mandant sicherer als Metadatenfilter?","Er isoliert stärker: Eine Anfrage erreicht die Daten eines anderen Mandanten nicht, selbst wenn ein Filter fehlt, und Offboarding heißt den Namespace löschen. Pinecone empfiehlt einen Namespace pro Mandant. Innerhalb eines Mandanten braucht man trotzdem Filter auf Dokumentebene.",{"q":90,"a":91},"Können Embeddings den Originaltext verraten?","Ja, bis zu einem gewissen Grad. Morris und Kollegen zeigten 2023, dass ein iteratives Inversionsverfahren 92 % von Eingaben mit 32 Tokens exakt aus ihren Embeddings rekonstruierte. Den Vektorspeicher daher so schützen wie die Quelldokumente.",{"q":93,"a":94},"Wie teste ich, dass die Berechtigungen halten?","Canary-Dokumente anlegen, die nur eine Gruppe sehen darf, einen festen Satz Anfragen als Nutzer jeder Gruppe ausführen und prüfen, dass kein Canary-Chunk in einer Treffermenge auftaucht, in die er nicht gehört. In CI und nach jeder Änderung an der Rechte-Synchronisierung laufen lassen.",[96,99,102,105,108,111,114,117,120,123],{"id":97,"title":98},"how-rag-leaks","Wie gibt ein RAG-System Dokumente preis?",{"id":100,"title":101},"where-to-enforce","Wo sollte die Autorisierung stattfinden?",{"id":103,"title":104},"patterns","Getrennte Indizes, Vorfilter oder Nachfilter?",{"id":106,"title":107},"chunk-metadata","Was sollte jeder Chunk tragen?",{"id":109,"title":110},"pgvector-rls","Wie macht man das in pgvector?",{"id":112,"title":113},"vector-databases","Was bieten Qdrant, Pinecone und Azure AI Search?",{"id":115,"title":116},"permission-sync","Wie hält man Berechtigungen synchron?",{"id":118,"title":119},"derived-data","Was ist mit Caches, Zusammenfassungen und Embeddings?",{"id":121,"title":122},"leak-tests","Wie testet man, dass nichts durchsickert?",{"id":124,"title":125},"sources","Quellen",[127,131,134,137,140,169,178,179,182,191,203,204,207,255,263,264,271,273,280,281,288,290,310,311,340,341,344,369,370,378,381,382,385,387,395,396],{"type":128,"content":129},"paragraph",[130],"Der schnellste Weg zu einem internen RAG-Assistenten ist, alles mit einem Dienstkonto zu indexieren und das Modell antworten zu lassen. Es ist auch der schnellste Weg, damit ein Lehrling nach „den Gehaltsbändern dieses Jahres“ fragt und eine Antwort mit Quellenangabe aus einer HR-Tabelle bekommt. Das Quellsystem hatte Berechtigungen; der Index hat sie plattgemacht.",{"type":128,"content":132},[133],"OWASP führt das als LLM08:2025, Schwächen bei Vektoren und Embeddings: schwache Zugriffskontrollen auf Embeddings, Lecks zwischen Mandanten in geteilten Vektordatenbanken und Embedding-Inversion. Dieser Beitrag ist die praktische Seite: wo Berechtigungen durchgesetzt werden, was jeder Chunk tragen muss, wie das in pgvector, Qdrant, Pinecone und Azure AI Search geht, wie Rechte synchron bleiben und wie man testet, dass nichts durchsickert.",{"type":135,"level":136,"id":97,"text":98},"heading",2,{"type":128,"content":138},[139],"In den Systemen, die ich prüfe, entstehen Lecks selten durch einen raffinierten Angriff. Sie entstehen dort, wo Berechtigungen nie angehängt wurden:",{"type":141,"items":142},"list",[143,149,154,159,164],[144,148],{"tag":145,"children":146},"strong",[147],"Ein Index ohne ACLs."," Inhalte wurden mit einem Admin- oder Dienstkonto gecrawlt, und Chunks tragen keine Information darüber, wer sie lesen darf.",[150,153],{"tag":145,"children":151},[152],"Filter, die offen versagen."," Ein fehlender Gruppen-Claim erzeugt einen leeren Filter, und ein leerer Filter passt auf alles.",[155,158],{"tag":145,"children":156},[157],"Veraltete Berechtigungen."," Jemand wurde letzte Woche aus einer SharePoint-Site entfernt; der Index führt die Person noch.",[160,163],{"tag":145,"children":161},[162],"Abgeleitete Daten."," Ein semantischer Cache, ein Gesprächsgedächtnis oder eine Zusammenfassung mehrerer Dokumente beantwortet einem zweiten Nutzer Fragen aus Material, das nur der erste sehen durfte.",[165,168],{"tag":145,"children":166},[167],"Überprivilegierte Agenten."," Ein Retrieval-Werkzeug läuft mit dem Dienstkonto statt mit der Identität des Nutzers, sodass der Agent holen kann, was der Nutzer nicht darf.",{"type":128,"content":170},[171,172,177],"Der letzte Punkt ist die allgemeine Regel aus ",{"tag":173,"to":174,"children":175},"link","\u002Fblog\u002Fai-agent-identity-least-privilege",[176],"KI-Agenten sind Identitäten",": Retrieval sollte im Namen des Nutzers handeln, mit dessen Rechten, nicht mit den Rechten des Systems, das es betreibt.",{"type":135,"level":136,"id":100,"text":101},{"type":128,"content":180},[181],"In der Retrieval-Abfrage, bevor irgendetwas das Modell erreicht. Ist ein Chunk einmal im Prompt, hält ihn keine Anweisung zuverlässig aus der Antwort heraus, und Prompt Injection kann direkt nach ihm fragen. Der Ablauf ist in jedem Stack gleich: Nutzer authentifizieren, Gruppen auflösen, diese Gruppen als Filter zur Suche hinzufügen und nur die verbleibenden Chunks an Reranking und Generierung geben.",{"type":183,"attrs":184,"inner":188,"caption":189},"diagram",{"viewBox":185,"role":186,"aria-labelledby":187},"0 0 720 170","img","acl1-t acl1-d","\u003Ctitle id=\"acl1-t\">Berechtigungsbewusstes Retrieval\u003C\u002Ftitle>\u003Cdesc id=\"acl1-d\">Das Nutzertoken wird zu Mandant und Gruppenliste aufgelöst. Die Suchabfrage enthält einen Filter auf diese Gruppen, sodass nicht berechtigte Chunks nie Kandidaten werden. Reranking und Sprachmodell sehen nur erlaubte Chunks.\u003C\u002Fdesc>\u003Cdefs>\u003Cmarker id=\"acl1-ah\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\">\u003Cpath d=\"M0 0L10 5L0 10z\" class=\"d-head\" \u002F>\u003C\u002Fmarker>\u003C\u002Fdefs>\u003Crect x=\"20\" y=\"47\" width=\"118\" height=\"76\" rx=\"10\" class=\"d-box\" \u002F>\u003Ctext x=\"79\" y=\"81\" text-anchor=\"middle\" class=\"d-text\">Nutzertoken\u003C\u002Ftext>\u003Ctext x=\"79\" y=\"103\" text-anchor=\"middle\" class=\"d-small\">OIDC, Entra\u003C\u002Ftext>\u003Cpath d=\"M138 85H158\" class=\"d-line\" marker-end=\"url(#acl1-ah)\" \u002F>\u003Crect x=\"160\" y=\"47\" width=\"118\" height=\"76\" rx=\"10\" class=\"d-accent\" \u002F>\u003Ctext x=\"220\" y=\"81\" text-anchor=\"middle\" class=\"d-text\">Auflösen\u003C\u002Ftext>\u003Ctext x=\"220\" y=\"103\" text-anchor=\"middle\" class=\"d-small\">Mandant, Gruppen\u003C\u002Ftext>\u003Cpath d=\"M279 85H299\" class=\"d-line\" marker-end=\"url(#acl1-ah)\" \u002F>\u003Crect x=\"301\" y=\"47\" width=\"118\" height=\"76\" rx=\"10\" class=\"d-gold\" \u002F>\u003Ctext x=\"360\" y=\"81\" text-anchor=\"middle\" class=\"d-text\">Gefilterte Suche\u003C\u002Ftext>\u003Ctext x=\"360\" y=\"103\" text-anchor=\"middle\" class=\"d-small\">ACL in Abfrage\u003C\u002Ftext>\u003Cpath d=\"M419 85H439\" class=\"d-line\" marker-end=\"url(#acl1-ah)\" \u002F>\u003Crect x=\"441\" y=\"47\" width=\"118\" height=\"76\" rx=\"10\" class=\"d-box\" \u002F>\u003Ctext x=\"500\" y=\"81\" text-anchor=\"middle\" class=\"d-text\">Rerank\u003C\u002Ftext>\u003Ctext x=\"500\" y=\"103\" text-anchor=\"middle\" class=\"d-small\">nur erlaubte\u003C\u002Ftext>\u003Cpath d=\"M560 85H580\" class=\"d-line\" marker-end=\"url(#acl1-ah)\" \u002F>\u003Crect x=\"582\" y=\"47\" width=\"118\" height=\"76\" rx=\"10\" class=\"d-mint\" \u002F>\u003Ctext x=\"641\" y=\"81\" text-anchor=\"middle\" class=\"d-text\">LLM\u003C\u002Ftext>\u003Ctext x=\"641\" y=\"103\" text-anchor=\"middle\" class=\"d-small\">zitiert Quellen\u003C\u002Ftext>",[190],"Schlägt die Gruppenauflösung fehl, schlägt die Anfrage fehl; sie fällt nie auf eine ungefilterte Suche zurück.",{"type":192,"variant":193,"title":194,"body":195},"callout","warn","Der System-Prompt ist keine Zugriffskontrolle",[196],[197,198,202],"„Gib HR-Dokumente nicht an Nicht-HR-Personal weiter“ im System-Prompt ist eine Hoffnung, keine Kontrolle. Alles im Kontextfenster kann in der Ausgabe landen, besonders bei den Injection-Mustern aus ",{"tag":173,"to":199,"children":200},"\u002Fblog\u002Fprompt-injection-lethal-trifecta-patterns",[201],"dem tödlichen Dreigespann",". Nicht berechtigten Text stattdessen aus dem Kontext heraushalten.",{"type":135,"level":136,"id":103,"text":104},{"type":128,"content":205},[206],"Es gibt vier Muster, und die meisten echten Systeme kombinieren zwei: harte Isolation zwischen Mandanten und Filter auf Dokumentebene innerhalb jedes Mandanten.",{"type":208,"head":209,"rows":218},"table",[210,212,214,216],[211],"Muster",[213],"Funktionsweise",[215],"Stärke",[217],"Schwäche",[219,228,237,246],[220,222,224,226],[221],"Index oder Namespace pro Mandant",[223],"Anfragen treffen nur die Partition eines Mandanten",[225],"Fehlender Filter kann Mandanten nicht überqueren; Löschen fürs Offboarding",[227],"Keine Dokumentrechte innerhalb eines Mandanten",[229,231,233,235],[230],"Metadaten-Vorfilter",[232],"Erlaubte Gruppen pro Chunk, Filter in der Abfrage",[234],"Nicht berechtigte Chunks werden nie Kandidaten",[236],"ACLs müssen in den Index synchronisiert werden",[238,240,242,244],[239],"Nachfilter mit Autorisierungsdienst",[241],"Kandidaten holen, dann jeden gegen OpenFGA o. Ä. prüfen",[243],"Immer aktuelle Rechte",[245],"Mehr abrufen, leere Seiten, Latenz",[247,249,251,253],[248],"Row-Level Security in der Datenbank",[250],"Postgres-Richtlinien filtern Zeilen für die Rolle der Sitzung",[252],"Standardmäßig verweigert, unterhalb der Anwendung erzwungen",[254],"Nur für Postgres; Recall-Falle mit ANN-Indizes",{"type":128,"content":256},[257,258,262],"OpenFGA beschreibt die Nachfilter-Varianten: jeden Kandidaten auf eine ",{"tag":259,"children":260},"code",[261],"can_view","-Relation prüfen oder einmal list-objects aufrufen, um alle Dokumente zu erhalten, die der Nutzer lesen darf, und mit den Kandidaten zu schneiden. Empfohlen werden Einzelprüfungen für kleine Mengen und list-objects bei größeren. Der Preis jedes Nachfilters: Man muss mehr abrufen als nötig, weil manche Kandidaten wegfallen.",{"type":135,"level":136,"id":106,"text":107},{"type":128,"content":265},[266,267,270],"Chunks erben die Berechtigungen ihres Quelldokuments. Wo möglich Gruppen statt einzelner Nutzer speichern; Microsoft gibt denselben Rat für ACL-geschützte Inhalte in Azure AI Search, und Pinecone nennt Filtern über lange Listen von Nutzer-IDs ein Anti-Pattern, mit einem Limit von 10.000 Werten pro ",{"tag":259,"children":268},[269],"$in","-Operator. Eine minimale Nutzlast:",{"type":259,"code":272},"{\n  \"chunk_id\": \"sp-hr-0412#7\",\n  \"tenant_id\": \"acme\",\n  \"doc_id\": \"sp-hr-0412\",\n  \"source\": \"sharepoint:\u002F\u002Fhr\u002Fsalary-bands-2026.xlsx\",\n  \"allowed_groups\": [\"grp-hr\", \"grp-exec\"],\n  \"classification\": \"confidential\",\n  \"acl_version\": \"2026-10-16T22:05:11Z\",\n  \"text\": \"...\"\n}",{"type":128,"content":274},[275,276,279],"Das Feld ",{"tag":259,"children":277},[278],"acl_version"," macht die Synchronisierung prüfbar: Man sieht, wie alt die Rechte jedes Chunks sind, und findet Chunks, die ein Update verpasst haben. Für alles, was aus mehreren Dokumenten abgeleitet ist, etwa eine Zusammenfassung, die Schnittmenge ihrer Gruppen nehmen, nicht die Vereinigung.",{"type":135,"level":136,"id":109,"text":110},{"type":128,"content":282},[283,284,287],"Row-Level Security in Postgres legt den Filter unter die Anwendung. Einmal für eine Tabelle aktiviert, muss jeder normale Zugriff durch eine Richtlinie erlaubt sein; ohne Richtlinie gilt Verweigerung. Superuser, Rollen mit BYPASSRLS und normalerweise der Tabelleneigentümer umgehen sie, deshalb muss die Anwendung mit einer eigenen Rolle verbinden, und ",{"tag":259,"children":285},[286],"FORCE ROW LEVEL SECURITY"," unterwirft auch den Eigentümer der Richtlinie.",{"type":259,"code":289},"ALTER TABLE chunks ENABLE ROW LEVEL SECURITY;\nALTER TABLE chunks FORCE ROW LEVEL SECURITY;\n\n-- The app sets the caller's tenant and groups per transaction.\nCREATE POLICY chunk_read ON chunks FOR SELECT TO rag_app\n  USING (\n    tenant_id = current_setting('app.tenant_id')\n    AND allowed_groups && string_to_array(current_setting('app.groups'), ',')\n  );\n\nBEGIN;\nSET LOCAL app.tenant_id = 'acme';\nSET LOCAL app.groups = 'grp-sales,grp-all';\nSET LOCAL hnsw.iterative_scan = relaxed_order;   -- pgvector 0.8.0+\nSELECT chunk_id, text FROM chunks\nORDER BY embedding \u003C=> $1 LIMIT 20;\nCOMMIT;",{"type":128,"content":291},[292,293,296,297,300,301,304,305,309],"Die letzte Einstellung ist wichtiger, als sie aussieht. pgvector wendet Filter nach dem Scan des approximativen Index an, und mit dem Standardwert ",{"tag":259,"children":294},[295],"hnsw.ef_search"," von 40 lässt ein Filter, der 10 % der Zeilen trifft, etwa 4 Ergebnisse übrig. Ein Berechtigungsfilter ist genau so ein Filter, und das Symptom ist kein Leck, sondern ein Assistent, der für Nutzer mit wenigen Rechten Dokumente „nicht findet“. Iterative Index-Scans, eingeführt in pgvector 0.8.0, scannen weiter, bis genug Zeilen passen, bis zu ",{"tag":259,"children":298},[299],"hnsw.max_scan_tuples"," (standardmäßig 20.000). Für Mandanten helfen auch ein B-Tree-Index auf ",{"tag":259,"children":302},[303],"tenant_id"," oder Listenpartitionierung nach Mandant. Mein Vergleich von ",{"tag":173,"to":306,"children":307},"\u002Fblog\u002Fpgvector-vs-vector-databases",[308],"pgvector und Vektordatenbanken"," zeigt, wann das reicht.",{"type":135,"level":136,"id":112,"text":113},{"type":141,"items":312},[313,326,331],[314,317,318,321,322,325],{"tag":145,"children":315},[316],"Qdrant"," empfiehlt eine Collection mit Mandantenfeld statt einer Collection pro Mandant. Ein Keyword-Payload-Index mit ",{"tag":259,"children":319},[320],"is_tenant"," auf true (ab v1.11) speichert die Vektoren jedes Mandanten zusammen, jede Anfrage trägt einen ",{"tag":259,"children":323},[324],"must","-Filter auf den Mandanten, und ab v1.16 befördert gestufte Mandantenfähigkeit große Mandanten in einen eigenen Shard. Gruppen auf Dokumentebene kommen als weiterer Filter in die Payload.",[327,330],{"tag":145,"children":328},[329],"Pinecone"," empfiehlt einen Namespace pro Mandant in einem Serverless-Index. Namespaces werden getrennt gespeichert, was Pinecone als physische Isolation beschreibt, und Offboarding heißt Namespace löschen. Anfragen werden nach Namespace-Größe abgerechnet; das Filtern eines geteilten 100-GB-Namespace kostet also 100-mal mehr als die Abfrage eines 1-GB-Mandanten-Namespace.",[332,335,336,339],{"tag":145,"children":333},[334],"Azure AI Search"," unterstützt Sicherheitsfilter, einen einfachen Zeichenkettenvergleich auf einem Identitätsfeld, das die Anwendung befüllt, und in der Vorschau native ACLs und RBAC-Scopes auf Dokumentebene, SharePoint-ACLs und Purview-Vertraulichkeitsbezeichnungen, durchgesetzt über das Entra-Token des Nutzers im Header ",{"tag":259,"children":337},[338],"x-ms-query-source-authorization",". Microsoft stellt klar, dass Sicherheitsfilter Zeichenkettenvergleich sind, keine Authentifizierung; die Anwendung muss die Identität also zuerst prüfen.",{"type":135,"level":136,"id":115,"text":116},{"type":128,"content":342},[343],"Ein Index ist eine Kopie, und Kopien veralten. Microsofts Dokumentation sagt es direkt: Rechteänderungen im Quellsystem erscheinen erst in den Suchergebnissen, wenn die Metadaten in den Index synchronisiert sind, und bei SharePoint brauchen Änderungen, die von übergeordneter Site, Bibliothek oder Ordner geerbt werden, eine explizite Aktualisierung. Jeder andere Stack hat dieselbe Eigenschaft, dokumentiert oder nicht. Drei Maßnahmen halten das Fenster klein:",{"type":141,"ordered":345,"items":346},true,[347,359,364],[348,351,352,355,356,358],{"tag":145,"children":349},[350],"ACLs getrennt vom Inhalt synchronisieren."," ",{"tag":259,"children":353},[354],"allowed_groups"," zu aktualisieren ist ein Metadaten-Schreibvorgang, kein Neu-Embedding. Viel häufiger ausführen als die Inhaltsindexierung und alarmieren, wenn ",{"tag":259,"children":357},[278]," zurückfällt.",[360,363],{"tag":145,"children":361},[362],"Gruppen bei der Anfrage auflösen."," Gruppen an Chunks speichern und die aktuelle Gruppenmitgliedschaft des Nutzers pro Anfrage beim Identitätsanbieter auflösen, damit das Entfernen aus einer Gruppe sofort wirkt.",[365,368],{"tag":145,"children":366},[367],"Quellen mit hohem Risiko live nachprüfen."," Für HR-, Rechts- oder Vorstandsmaterial einen Nachfilter gegen das Quellsystem oder einen Autorisierungsdienst für die finalen Kandidaten ergänzen und die zusätzliche Latenz nur für diese Bestände akzeptieren.",{"type":135,"level":136,"id":118,"text":119},{"type":128,"content":371},[372,373,377],"Alles, was aus Dokumenten berechnet wird, erbt deren Schutzbedarf. Ein semantischer Cache muss die Berechtigungsmenge des Nutzers im Schlüssel tragen, sonst wird die Antwort eines Nutzers einem anderen ausgeliefert; die Abgrenzung habe ich in ",{"tag":173,"to":374,"children":375},"\u002Fblog\u002Fsemantic-caching-llm-responses",[376],"semantisches Caching"," beschrieben. Gesprächsgedächtnis gehört einem Nutzer. Zusammenfassungen, Entitätsbeschreibungen und Chunk-Kontexte über mehrere Dokumente erhalten die Schnittmenge ihrer Gruppen.",{"type":128,"content":379},[380],"Auch Embeddings sind nicht anonym. Morris und Kollegen zeigten 2023, dass ein iteratives Inversionsverfahren 92 % von Eingaben mit 32 Tokens exakt aus ihren Embeddings rekonstruierte und aus klinischen Notizen vollständige Namen zurückgewann. Dem Vektorspeicher dieselbe Netzwerkisolation, Verschlüsselung und Zugriffsprotokollierung geben wie den Quelldokumenten und ihn in Löschanfragen einbeziehen.",{"type":135,"level":136,"id":121,"text":122},{"type":128,"content":383},[384],"Die Retrieval-Schicht testen, nicht die Antworten. Ein Modell kann sich weigern, einen erhaltenen Chunk zu zitieren, und verdeckt damit den Fehler. Canary-Dokumente mit eindeutigen Markierungen anlegen, jedes für genau eine Gruppe sichtbar, und auf die abgerufenen Chunk-IDs prüfen:",{"type":259,"code":386},"import pytest\n\nPERSONAS = {\"sales\": [\"grp-sales\"], \"hr\": [\"grp-hr\"], \"none\": []}\nCANARIES = {\"canary-hr\": \"grp-hr\", \"canary-sales\": \"grp-sales\"}\nQUERIES = [\"salary bands\", \"canary report\", \"confidential\", \"*\"]\n\n@pytest.mark.parametrize(\"persona,groups\", PERSONAS.items())\n@pytest.mark.parametrize(\"query\", QUERIES)\ndef test_no_canary_leaks(persona, groups, query):\n    hits = retrieve(query, tenant=\"acme\", groups=groups, k=50)\n    for doc_id, owner_group in CANARIES.items():\n        if owner_group not in groups:\n            assert all(h.doc_id != doc_id for h in hits), (persona, query, doc_id)\n\ndef test_missing_groups_fail_closed():\n    with pytest.raises(PermissionError):\n        retrieve(\"anything\", tenant=\"acme\", groups=None, k=10)",{"type":128,"content":388},[389,390,394],"Zwei weitere Prüfungen ergänzen: Widerrufslatenz, indem man einen Testnutzer aus einer Gruppe entfernt und misst, wie lange es dauert, bis der Canary verschwindet, und Mandantenisolation, indem man mit einem gültigen Token für Mandant A gegen den Namespace von Mandant B abfragt. Die Suite in CI und nach jeder Änderung am Sync-Job laufen lassen. Zugriffskontrolle gehört neben die Abwehr von ",{"tag":173,"to":391,"children":392},"\u002Fblog\u002Frag-poisoning-knowledge-base-attacks",[393],"RAG-Poisoning",": Beide schützen die Wissensbasis, die eine gegen Lesen, die andere gegen Schreiben.",{"type":135,"level":136,"id":124,"text":125},{"type":141,"ordered":345,"items":397},[398,402,405,408,411,414,417,420],[399],{"tag":400,"href":40,"children":401},"a",[39],[403],{"tag":400,"href":43,"children":404},[42],[406],{"tag":400,"href":46,"children":407},[45],[409],{"tag":400,"href":49,"children":410},[48],[412],{"tag":400,"href":52,"children":413},[51],[415],{"tag":400,"href":55,"children":416},[54],[418],{"tag":400,"href":58,"children":419},[57],[421],{"tag":400,"href":61,"children":422},[60],[424,496,554,607],{"slug":425,"published":5,"minutes":6,"category":7,"tags":426,"keywords":430,"about":443,"sources":453,"cover":490,"og":491,"expertise":64,"locales":492,"lang":67,"title":493,"description":494,"coverAlt":495},"embedding-model-selection-2026",[427,9,428,13,429],"Embeddings","MTEB","Model selection",[431,432,433,434,435,436,437,438,439,440,441,442],"best embedding model 2026","how to choose an embedding model","embedding model comparison","MTEB leaderboard explained","RTEB benchmark","open source embedding model","multilingual embedding model","voyage-4 vs openai embeddings","Qwen3-Embedding","EmbeddingGemma","embedding model for RAG","switching embedding models re-embed",[444,447,450],{"name":445,"url":446},"Word embedding","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FWord_embedding",{"name":448,"url":449},"Information retrieval","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FInformation_retrieval",{"name":451,"url":452},"Discounted cumulative gain","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FDiscounted_cumulative_gain",[454,457,460,463,466,469,472,475,478,481,484,487],{"title":455,"url":456},"Enevoldsen et al.: MMTEB, Massive Multilingual Text Embedding Benchmark (2025)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2502.13595",{"title":458,"url":459},"Hugging Face: Introducing RTEB, a new standard for retrieval evaluation (Oct 2025)","https:\u002F\u002Fhuggingface.co\u002Fblog\u002Frteb",{"title":461,"url":462},"OpenAI: Vector embeddings guide","https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Fguides\u002Fembeddings",{"title":464,"url":465},"OpenAI: API pricing","https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Fpricing",{"title":467,"url":468},"Voyage AI: The Voyage 4 model family, shared embedding space with MoE architecture (Jan 2026)","https:\u002F\u002Fblog.voyageai.com\u002F2026\u002F01\u002F15\u002Fvoyage-4\u002F",{"title":470,"url":471},"Voyage AI: Text embeddings documentation","https:\u002F\u002Fdocs.voyageai.com\u002Fdocs\u002Fembeddings",{"title":473,"url":474},"Voyage AI: Pricing","https:\u002F\u002Fdocs.voyageai.com\u002Fdocs\u002Fpricing",{"title":476,"url":477},"Google: Gemini API embeddings documentation","https:\u002F\u002Fai.google.dev\u002Fgemini-api\u002Fdocs\u002Fembeddings",{"title":479,"url":480},"Google: Gemini API pricing","https:\u002F\u002Fai.google.dev\u002Fgemini-api\u002Fdocs\u002Fpricing",{"title":482,"url":483},"Cohere: Embed models documentation","https:\u002F\u002Fdocs.cohere.com\u002Fdocs\u002Fcohere-embed",{"title":485,"url":486},"Qwen: Qwen3-Embedding-8B model card","https:\u002F\u002Fhuggingface.co\u002FQwen\u002FQwen3-Embedding-8B",{"title":488,"url":489},"Google Developers Blog: Introducing EmbeddingGemma (Sep 2025)","https:\u002F\u002Fdevelopers.googleblog.com\u002Fen\u002Fintroducing-embeddinggemma\u002F","\u002Fimages\u002Fblog\u002Fembedding-model-selection-2026\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fembedding-model-selection-2026\u002Fog.jpg",[66,67,68],"Embedding-Modell wählen 2026: Leaderboards, Kosten und ein Vergleichstest mit eigenen Daten","Wie man 2026 ein Embedding-Modell für RAG wählt: was MTEB und RTEB aussagen, API oder offene Gewichte, Preise, Dimensionen und ein einwöchiger Vergleichstest.","Drei Säulen aus gestapelten Blöcken, die mittlere am höchsten, jede mit kurzem Balken und weiter Klammer.",{"slug":497,"published":5,"minutes":498,"category":7,"tags":499,"keywords":503,"about":515,"sources":523,"cover":548,"og":549,"expertise":64,"locales":550,"lang":67,"title":551,"description":552,"coverAlt":553},"contextual-retrieval-late-chunking",10,[9,500,427,501,502],"Chunking","Contextual retrieval","Late chunking",[504,505,506,507,508,509,510,511,512,513,514],"contextual retrieval","anthropic contextual retrieval","late chunking","contextual chunk embeddings","contextual embeddings rag","contextual bm25","chunk context rag","voyage-context-3","voyage-context-4","late chunking vs contextual retrieval","rag chunking context loss",[516,517,520],{"name":35,"url":36},{"name":518,"url":519},"Okapi BM25","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FOkapi_BM25",{"name":521,"url":522},"Sentence embedding","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FSentence_embedding",[524,527,530,533,536,539,542,545],{"title":525,"url":526},"Anthropic: Introducing Contextual Retrieval (Sep 2024)","https:\u002F\u002Fwww.anthropic.com\u002Fnews\u002Fcontextual-retrieval",{"title":528,"url":529},"Günther et al.: Late Chunking, Contextual Chunk Embeddings Using Long-Context Embedding Models (2024, rev. 2025)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2409.04701",{"title":531,"url":532},"Jina AI: Late Chunking in Long-Context Embedding Models (Aug 2024)","https:\u002F\u002Fjina.ai\u002Fnews\u002Flate-chunking-in-long-context-embedding-models\u002F",{"title":534,"url":535},"Voyage AI: Introducing voyage-context-3 (Jul 2025)","https:\u002F\u002Fblog.voyageai.com\u002F2025\u002F07\u002F23\u002Fvoyage-context-3\u002F",{"title":537,"url":538},"Voyage AI: voyage-context-4 (Jun 2026)","https:\u002F\u002Fblog.voyageai.com\u002F2026\u002F06\u002F29\u002Fvoyage-context-4\u002F",{"title":540,"url":541},"Voyage AI: Contextualized chunk embeddings documentation","https:\u002F\u002Fdocs.voyageai.com\u002Fdocs\u002Fcontextualized-chunk-embeddings",{"title":543,"url":544},"Anthropic: Claude API pricing","https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fabout-claude\u002Fpricing",{"title":546,"url":547},"Qu, Tu and Bao: Is Semantic Chunking Worth the Computational Cost? (2024)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2410.13070","\u002Fimages\u002Fblog\u002Fcontextual-retrieval-late-chunking\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fcontextual-retrieval-late-chunking\u002Fog.jpg",[66,67,68],"Contextual Retrieval und Late Chunking: RAG-Chunks ihren Kontext zurückgeben","Chunks verlieren ihr Dokument. Wie Contextual Retrieval, Late Chunking und kontextuelle Embeddings das beheben, was sie kosten, wann man verzichtet.","Vier lose Quadrate, unten von einer breiten Klammer gebündelt und je nach oben mit einer großen Fläche verbunden.",{"slug":555,"published":556,"minutes":6,"category":7,"tags":557,"keywords":562,"about":573,"sources":581,"cover":601,"og":602,"expertise":64,"locales":603,"lang":67,"title":604,"description":605,"coverAlt":606},"pdf-document-parsing-for-rag","2026-10-16",[9,558,559,560,561],"PDF parsing","OCR","Docling","Document AI",[563,564,565,566,567,568,569,570,571,572],"pdf parsing for rag","best pdf parser for rag","docling vs marker","marker vs mineru","pdf to markdown for llm","extract tables from pdf for rag","ocr for rag pipeline","olmocr bench","scanned pdf rag","document parsing llm",[574,577,580],{"name":575,"url":576},"PDF","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FPDF",{"name":578,"url":579},"Optical character recognition","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FOptical_character_recognition",{"name":35,"url":36},[582,585,588,591,594,597,600],{"title":583,"url":584},"Docling: README, features and license (GitHub)","https:\u002F\u002Fgithub.com\u002Fdocling-project\u002Fdocling",{"title":586,"url":587},"Auer et al.: Docling: An Efficient Open-Source Toolkit for AI-driven Document Conversion (2025)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2501.17887",{"title":589,"url":590},"Datalab: Marker README, olmOCR-bench results and license (GitHub)","https:\u002F\u002Fgithub.com\u002Fdatalab-to\u002Fmarker",{"title":592,"url":593},"OpenDataLab: MinerU README and license (GitHub)","https:\u002F\u002Fgithub.com\u002Fopendatalab\u002FMinerU",{"title":595,"url":596},"Poznanski et al.: olmOCR: Unlocking Trillions of Tokens in PDFs with Vision Language Models (2025)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2502.18443",{"title":598,"url":599},"Claude Platform Docs: PDF support","https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fbuild-with-claude\u002Fpdf-support",{"title":525,"url":526},"\u002Fimages\u002Fblog\u002Fpdf-document-parsing-for-rag\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fpdf-document-parsing-for-rag\u002Fog.jpg",[66,67,68],"PDF-Parsing für RAG: Layout-Pipelines, OCR und Vision-Modelle im Vergleich","Warum das PDF-Parsing die RAG-Qualität bestimmt, wie sich Docling, Marker, MinerU und VLM-OCR unterscheiden und wie man einen Parser selbst testet.","Unregelmäßige Blöcke auf einem Blatt werden zu einer gleichmäßigen Reihe auf einem zweiten Blatt.",{"slug":608,"published":556,"minutes":609,"category":7,"tags":610,"keywords":614,"about":624,"sources":634,"cover":655,"og":656,"expertise":64,"locales":657,"lang":67,"title":658,"description":659,"coverAlt":660},"multilingual-rag-german-hungarian",7,[9,611,427,612,613],"Multilingual","German","Hungarian",[615,616,617,618,437,619,620,621,622,623],"multilingual rag","german rag embeddings","hungarian nlp search","cross-lingual retrieval","bge-m3 german","german compound words search","hungarian stemming postgres","multilingual-e5-large-instruct","qwen3 embedding multilingual",[625,628,631],{"name":626,"url":627},"Cross-language information retrieval","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FCross-language_information_retrieval",{"name":629,"url":630},"Agglutinative language","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FAgglutinative_language",{"name":632,"url":633},"Compound (linguistics)","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FCompound_(linguistics)",[635,637,640,643,646,649,652],{"title":636,"url":456},"Enevoldsen et al.: MMTEB: Massive Multilingual Text Embedding Benchmark (2025)",{"title":638,"url":639},"Chen et al.: M3-Embedding (BGE-M3): Multi-Linguality, Multi-Functionality, Multi-Granularity (2024)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2402.03216",{"title":641,"url":642},"Zhang et al.: Qwen3 Embedding: Advancing Text Embedding and Reranking Through Foundation Models (2025)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2506.05176",{"title":644,"url":645},"Hugging Face: intfloat\u002Fmultilingual-e5-large-instruct model card","https:\u002F\u002Fhuggingface.co\u002Fintfloat\u002Fmultilingual-e5-large-instruct",{"title":647,"url":648},"Elasticsearch Reference: Hyphenation decompounder token filter","https:\u002F\u002Fwww.elastic.co\u002Fdocs\u002Freference\u002Ftext-analysis\u002Fanalysis-hyp-decomp-tokenfilter",{"title":650,"url":651},"PostgreSQL 18 Documentation: Text search dictionaries","https:\u002F\u002Fwww.postgresql.org\u002Fdocs\u002Fcurrent\u002Ftextsearch-dictionaries.html",{"title":653,"url":654},"Snowball: stemming algorithms by language","https:\u002F\u002Fsnowballstem.org\u002Falgorithms\u002F","\u002Fimages\u002Fblog\u002Fmultilingual-rag-german-hungarian\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fmultilingual-rag-german-hungarian\u002Fog.jpg",[66,67,68],"Mehrsprachiges RAG für Deutsch und Ungarisch: Embeddings, Komposita und sprachübergreifende Suche","RAG über deutsche und ungarische Inhalte: mehrsprachige Embeddings, Komposita, Stemming, Akzente und Evaluation pro Sprache.","Zwei Reihen kleiner Quadrate, jedes mit einem Punkt darüber, fließen in ein hohes Rechteck.",1792222777462]