Every week, another enterprise announces a RAG-powered AI assistant. Legal teams get a contract review bot. Hospitals get a clinical decision support tool. Banks get a loan advisory chatbot. Universities get a student advising system.
Nearly all of them have the same structural compliance problem. And almost none of their builders have noticed it yet.
What RAG Actually Does
Retrieval-Augmented Generation works like this:
User query → Embedding model → Vector store retrieval → LLM → Response
The vector store retrieves the most semantically similar documents to the query — regardless of who owns them, who is authorized to see them, or what regulatory framework governs them. Those documents land in the LLM's context window. The LLM synthesizes a response.
By the time the LLM responds, the retrieval has already happened. The documents were already in the context. If any of those documents were unauthorized for the requesting user, the disclosure has already occurred.
This is not a theoretical risk. It is a structural property of every standard RAG implementation.
The Regulations That Make This a Legal Problem
Different industries, same architectural gap:
Healthcare — HIPAA (45 CFR § 164)
Protected Health Information (PHI) may only be accessed by authorized workforce members under a valid Business Associate Agreement. A clinical RAG system that retrieves Patient A's records into a query for Patient B's provider has violated the minimum necessary standard — regardless of whether the LLM's final response mentions Patient A by name.
Financial Services — GLBA, SOX
Customer financial records, account data, and trading information carry strict access controls. A wealth management AI that retrieves one client's portfolio details during another client's session has a data segregation failure — not a prompt failure.
Higher Education — FERPA (34 CFR § 99)
Student education records — transcripts, financial aid, disciplinary files — are protected by the Family Educational Rights and Privacy Act. A student advising chatbot that retrieves another student's academic record into its context, even briefly, has made an unauthorized disclosure under § 99.31.
Europe — GDPR (Article 5(1)(f))
Personal data must be processed with appropriate security to prevent unauthorized access. A RAG pipeline that does not enforce user-level access control on retrieved documents violates the integrity and confidentiality principle at the architecture level.
The common thread: Every one of these regulations requires that unauthorized data not be accessed — not merely that it not be mentioned in the final output.
Why Prompt-Layer Controls Fail
The instinct is to fix this at the prompt:
"Only discuss information belonging to the current user.
Ignore anything that belongs to someone else."
This approach has three failure modes that make it insufficient for any regulated deployment:
1. The document is already disclosed.
When the vector store retrieves an unauthorized document, it enters the LLM's context window. The LLM has processed it. Under HIPAA, FERPA, and GDPR, access — not just output — constitutes disclosure. A prompt instruction cannot retroactively undo retrieval.
2. Prompt injection overrides instructions.
OWASP's LLM Top 10 (LLM01) identifies prompt injection as the primary attack vector against LLM applications. An adversarial user input can override system prompt instructions. Any compliance control implemented purely as a prompt instruction is one injection payload away from failure.
3. LLMs hallucinate and leak.
Language models occasionally surface information from their context in unexpected ways — in reasoning chains, in partial responses, in error messages. A compliance architecture that relies on the LLM "knowing not to mention" certain content is not an architecture; it is a hope.
The Right Fix: Pre-Filter, Not Post-Filter
The solution is architecturally simple: enforce access control between the retriever and the LLM, before documents enter the context window.
Before (standard, non-compliant):
User query → Retriever → [all retrieved docs] → LLM → Response
After (compliant):
User query → Retriever → [Compliance Pre-Filter] → [authorized docs only] → LLM → Response
↓
Audit record (disclosure log)
The pre-filter does three things:
- Identity enforcement — documents tagged with a user or entity identifier are only passed to the LLM when the requesting user is authorized to see that entity's data
- Category authorization — documents in restricted categories (PHI, financial records, disciplinary files) require explicit authorization, not just identity match
- Audit logging — every retrieval event produces a structured disclosure record for compliance reporting
No document reaches the LLM context unless it has passed both checks. Shared content — knowledge base articles, policy documents, product documentation — passes through unchanged because it carries no identity metadata.
Implementation Across Frameworks
The enterprise-rag-patterns library implements this pattern across the major RAG frameworks:
Haystack 2.x
from haystack_integrations.components.filters.ferpa_filter import FERPAMetadataFilter
ferpa_filter = FERPAMetadataFilter(
student_id="stu_001",
institution_id="inst_abc",
authorized_categories=["academic_record", "financial_aid"],
requesting_user_id="advisor_007",
)
pipeline.add_component("ferpa_filter", ferpa_filter)
pipeline.connect("retriever.documents", "ferpa_filter.documents")
LangChain
from enterprise_rag_patterns import FERPAContextPolicy, make_enrollment_advisor_policy
policy = make_enrollment_advisor_policy(
student_id="stu_001",
institution_id="inst_abc",
)
filtered_docs = policy.filter(retrieved_docs)
HIPAA — any framework
from enterprise_rag_patterns.hipaa import HIPAADocumentFilter
hipaa_filter = HIPAADocumentFilter(
patient_id="pat_001",
provider_npi="1234567890",
authorized_purposes=["treatment", "care_coordination"],
)
GDPR — consent-gated retrieval
from enterprise_rag_patterns.gdpr import GDPRConsentFilter
gdpr_filter = GDPRConsentFilter(
data_subject_id="user_eu_001",
processing_purpose="personalization",
consent_store=your_consent_store,
)
Every filter emits a structured audit record on each run — timestamps, identity scope, categories disclosed, documents retrieved vs. disclosed. This is the disclosure log that HIPAA, FERPA, and GDPR all require in some form.
Document Metadata Design
The pattern requires that protected documents carry identity metadata at ingestion time:
# Protected record — only reaches authorized users
Document(
content="Patient presented with chest pain, BP 140/90...",
meta={
"patient_id": "pat_001",
"provider_npi": "1234567890",
"record_type": "clinical_note",
"data_classification": "PHI",
}
)
# Shared content — no identity metadata, passes through for all users
Document(
content="Standard dosing protocol for metformin...",
meta={"record_type": "clinical_guideline"}
)
This is a design decision that must be made at the data pipeline level — not at the RAG pipeline level. If documents are ingested without identity metadata, no filter can enforce access control because there is nothing to enforce against. Getting the metadata schema right at ingestion is the prerequisite for any compliant RAG deployment.
What This Does Not Replace
- Authentication — the pre-filter enforces an authorized identity scope; your application layer must establish that scope through authenticated session context
- Encryption at rest — vector store encryption is outside this pattern's scope
- Legal review — how your specific deployment maps to applicable regulations requires counsel; this pattern provides the technical control, not the legal interpretation
The Broader Point
The compliance gap in enterprise RAG is not a product gap — no major framework will solve this for you, because the solution requires knowing who the user is and what they are authorized to see. That context is application-specific. What a framework can provide is the enforcement mechanism; what your application must provide is the identity context.
The pre-filter pattern is that enforcement mechanism. It is not complex. It does not require a new architecture. It requires inserting one component between your retriever and your LLM — and designing your document metadata to carry the identity context the filter needs to do its job.
Every regulated enterprise deploying RAG today needs this. Most don't have it yet.
Resources:
-
enterprise-rag-patterns— github.com/ashutoshrana/enterprise-rag-patterns -
ferpa-haystack— github.com/ashutoshrana/ferpa-haystack -
regulated-ai-governance— github.com/ashutoshrana/regulated-ai-governance
Top comments (0)