MODULE 11/LESSON 2
🛡️ AI Safety & Guardrails

Enterprise Security & Compliance

Protecting Sensitive PII with Microsoft Presidio, Implementing Document-Level RBAC in RAG, and Compliance Engineering (GDPR/HIPAA)

14 min📊 Diagram
Enterprise AI deployment requires strict data governance. Sending raw customer PII (Social Security numbers, credit cards, medical records) to third-party LLMs violates GDPR, HIPAA, and SOC2. Furthermore, naive RAG implementations risk catastrophic data leaks if employees retrieve documents beyond their security clearance. Production systems demand automated PII masking middleware and strict Role-Based Access Control (RBAC) at the vector database layer.

Key Concepts

Automated PII Anonymization & Rehydration

Using Microsoft Presidio to detect entities (NAMES, EMAIL, PHONE, SSN) before API calls, swapping them with deterministic placeholders (`<PERSON_1>`), and rehydrating the response locally.

Vector Database Role-Based Access Control (RBAC)

Enforcing security boundaries during similarity search by embedding tenant_id, department_id, and allowed_roles into vector metadata, ensuring zero cross-tenant data leakage.

Postgres pgvector Row-Level Security (RLS)

Leveraging PostgreSQL Native Row-Level Security (RLS) to enforce permission boundaries at the database engine level, making unauthorized vector access structurally impossible.

Audit Logging & Data Lineage

Maintaining an immutable audit log of every prompt, anonymized payload, and retrieved document chunks for SOC2 compliance and security auditing.

Enterprise PII Masking & RBAC Architecture

Secure PII Middleware & Metadata RBAC Pipeline User Session JWT Auth & Roles Raw PII Prompt Microsoft Presidio Analyzer & Anonymizer Masks PII -> <PERSON_1> External LLM API GPT-4o / Claude 3.5 Zero PII Received pgvector / Pinecone DB Metadata Filter: tenant_id = X AND allowed_roles OVERLAPS ['manager'] Zero Cross-Tenant Leakage

1. Microsoft Presidio PII Masking Implementation

Presidio Analyzer identifies sensitive entities in text (emails, SSNs, credit cards), and Presidio Anonymizer replaces them with tokenized placeholders before sending the prompt to third-party LLM APIs.
middleware/pii_anonymizer.pypython
1from presidio_analyzer import AnalyzerEngine
2from presidio_anonymizer import AnonymizerEngine
3from presidio_anonymizer.entities import OperatorConfig
4
5class EnterprisePIIShield:
6    def __init__(self):
7        self.analyzer = AnalyzerEngine()
8        self.anonymizer = AnonymizerEngine()
9
10    def sanitize_prompt(self, user_prompt: str):
11        # 1. Analyze prompt for PII entities
12        results = self.analyzer.analyze(
13            text=user_prompt,
14            entities=["PHONE_NUMBER", "EMAIL_ADDRESS", "PERSON", "CREDIT_CARD"],
15            language="en"
16        )
17
18        # 2. Anonymize entities with deterministic placeholders
19        anonymized_result = self.anonymizer.anonymize(
20            text=user_prompt,
21            analyzer_results=results,
22            operators={
23                "DEFAULT": OperatorConfig("replace", {"new_value": "<REDACTED>"}),
24                "PERSON": OperatorConfig("replace", {"new_value": "<PERSON>"})
25            }
26        )
27        return anonymized_result.text
28
29# Example Usage:
30shield = EnterprisePIIShield()
31clean_prompt = shield.sanitize_prompt("Contact John Doe at john@example.com or 555-0199.")
32# Output: "Contact <PERSON> at <REDACTED> or <REDACTED>."

2. Document-Level RBAC with Metadata Filtering

In RAG pipelines, vector similarity search must enforce user permissions. By attaching tenant IDs and role lists to each document chunk's metadata, queries filter out unauthorized chunks before similarity scoring.
lib/rag-rbac-retriever.tstypescript
1import { VectorStore } from '@langchain/core/vectorstores';
2
3export async function searchVectorDBWithRBAC(
4  vectorStore: VectorStore,
5  query: string,
6  userSession: { tenantId: string; userRoles: string[] }
7) {
8  // Enforce metadata filter at search query time
9  const results = await vectorStore.similaritySearch(query, 5, {
10    // Construct boolean filter on Vector DB
11    $and: [
12      { tenant_id: { $eq: userSession.tenantId } },
13      { allowed_roles: { $in: userSession.userRoles } }
14    ]
15  });
16
17  return results;
18}

3. PostgreSQL Native Row-Level Security (RLS) for pgvector

Application-level filters can be bypassed due to developer error. PostgreSQL Native RLS enforces vector isolation directly inside the database kernel, preventing unauthorized data leaks regardless of application code bugs.
migrations/001_pgvector_rls.sqlsql
1-- Enable RLS on document embeddings table
2ALTER TABLE document_embeddings ENABLE ROW LEVEL SECURITY;
3
4-- Create policy enforcing tenant and role boundaries
5CREATE POLICY document_embeddings_rbac_policy ON document_embeddings
6    FOR SELECT
7    USING (
8        tenant_id = current_setting('app.current_tenant_id')::uuid
9        AND allowed_roles && string_to_array(current_setting('app.current_user_roles'), ',')
10    );
💡
Senior Architect Insight: Never rely solely on LLM system prompts for data security ('Do not reveal financial data to junior staff'). LLMs can be tricked via prompt injection. True enterprise security must be enforced deterministically using PII masking middleware and database-level RBAC filters.