Originally published at kunalganglani.com — read it there for inline code, hero image, and live links.
You’ll have field level redaction for RAG pipelines working end-to-end in about 60–90 minutes: a field-classified ingestion flow, deterministic redaction transforms, an optional reversible token vault, TTLs for every derived artifact, plus an audit trail and leakage tests you can hand to security and compliance.
This is the pattern I wish more teams shipped before they got dragged into a 6-week “privacy review” stalemate.
Most RAG privacy failures aren’t exotic model bugs. They’re boring pipeline gaps. Raw docs land in blob storage and never leave. PII gets embedded because nobody put a hard boundary before the embed step. Prompts and logs quietly capture sensitive text. Then, when an auditor asks “prove it,” you’ve got vibes and a Notion doc.
What is field-level redaction in a RAG pipeline
Field-level redaction in a RAG pipeline is the practice of detecting and transforming specific sensitive fields (PII/PHI/secrets) deterministically before they can be embedded, indexed, logged, or sent to an LLM, while preserving enough structure for retrieval and auditability.
Two properties matter more than people want to admit:
- Determinism: the same input field produces the same redacted output every time (under the same policy/version). If it’s not deterministic, you can’t diff it, test it, or explain it.
- Auditability: every transformation is traceable to a policy, a version, and an immutable event trail.
In practice, you’re building a data contract like this:
- Raw document: allowed in a tightly controlled store, short retention.
- Redacted document: safe for embedding and retrieval, longer retention.
- Token vault (optional): reversible mapping for approved re-identification.
- Derived artifacts (chunks, embeddings, vector rows, caches): TTL + deletion propagation.
If you’re also building AI agents, this isn’t optional. Agents widen the blast radius. They read more context, call more tools, and generate more “helpful” logs.
Where leakage happens in RAG (ingestion, chunking, embeddings, vector store, prompts, logs)
If your threat model stops at “the model provider might train on our prompts,” you’re missing the real leaks.
The usual leakage points in a RAG system are:
- Ingestion landing zone (raw PDFs/CSVs/emails): S3/R2/Blob storage becomes your accidental long-term archive.
- Parsing + chunking: extracted text pulls in headers/footers with names, emails, case numbers, customer IDs.
- Embedding step: the embedding model receives raw text. If that text includes PII, you already failed the basic premise.
- Vector database: your vector store turns into a searchable PII index. Even if the model never “prints” it, the retrieval layer can.
- Reranker and prompt assembly: retrieved chunks get concatenated into prompts. That prompt is now sensitive.
- Application logs: “debug logs” quietly persist full prompts/responses for months.
- Observability vendors: traces/spans can capture payloads unless you proactively redact.
- Human workflows: developers copy/paste traces into tickets and Slack because they’re trying to be helpful.
A concrete failure mode I’ve seen over and over: a single “helpful” log line like retrieved_context=... becomes a breach artifact. That’s why I treat LLM security and logging as one design problem, not two separate tickets.
If you want the broader system view, start from Prevent Sensitive Data Leakage in RAG: The 2026 Playbook and then come back here for the implementation details.
PII/PHI detection approaches (rules, NER, DLP tools)
Detection is where teams either over-engineer (ML for everything) or under-engineer (one regex, ship it).
The boring answer is the right one: use layered detection.
1) Field-aware detection (best ROI)
If your input is structured (CRM export, support tickets, HR records), you already know what the fields are. Use that.
Example schema (sensitivity classification):
-
customer.email→ PII.HIGH -
customer.name→ PII.MED -
customer.account_id→ PII.MED -
claim.diagnosis→ PHI.HIGH -
notes.free_text→ UNKNOWN (needs scanning)
This avoids the classic self-own: trying to “detect email addresses” inside a column literally named email.
2) Rules and regex (fast, deterministic)
Use regex for:
- emails
- phone numbers
- credit cards (with Luhn)
- known internal IDs (prefix-based)
Rules are cheap, deterministic, and easy to test. Yes, they create false positives. That’s not automatically bad. It’s only bad if you refuse to measure it and tune it.
3) NER (Named Entity Recognition) for messy text
NER is useful in:
- call center transcripts
- internal wikis
- long-form notes
Treat NER as a candidate generator, not a judge. In regulated environments, I’ve had better outcomes by making NER hits pass a second validation step (format checks, allowlists/denylists, or field context).
4) DLP tools (enterprise reality)
If you’re in bigco land, you’ll get asked: “Why not use our DLP?”
Sometimes you should.
DLP products help with centralized policy, consistent detection, and evidence. But they won’t magically give you determinism, and they definitely don’t understand your RAG-specific derived artifacts (chunks, embeddings, vector rows) unless you wire them in.
My stance: use DLP where it already exists, but still build a deterministic transformation layer you control.
Redaction vs anonymization vs pseudonymization vs tokenization
People mix these terms and then wonder why they can’t pass review.
- Redaction: remove sensitive data entirely (or replace with a placeholder). Not reversible.
- Masking: partially hide a value (e.g., last 4 digits). Usually reversible only by “knowing the original,” which you often don’t.
- Anonymization: transform so the subject cannot be re-identified. Hard to guarantee in practice.
- Pseudonymization: replace with a consistent pseudonym. Re-identification is possible with additional data.
- Tokenization: replace with a token that maps to the original in a controlled vault. Reversible by design.
For RAG, the only question that matters is: do you need re-identification at query time?
- If no: do deterministic redaction + keep raw docs behind strict access.
- If yes: do deterministic redaction for embedding + store reversible tokens + enforce “break-glass” access to detokenize.
This is not word games. It changes what you store, how long you keep it, and who gets to touch it.
How to implement deterministic redaction transforms
Deterministic redaction is the difference between “we think it’s safe” and “we can prove it’s safe.” Here’s the pattern I recommend.
The reference architecture (with explicit contracts)
Pipeline:
- Ingestion (raw doc) → compute
doc_id+content_hash - Field classifier → attach sensitivity tags per field
- Deterministic redactor → apply transforms (stable placeholders)
- Optional tokenization → store mapping in vault
- Chunk + embed → only redacted text crosses this boundary
- Vector DB write → attach metadata: policy version, transform ids, TTL
- Audit log append → every stage emits immutable events
If you’re running any of this inside production AI, write it down as a contract. Literally. Teams fail audits because the design only exists in someone’s head and three Slack threads.
Policy-as-data (YAML)
A simple policy file buys you two things: reproducibility and change control.
Example (illustrative):
- sensitivity levels:
PUBLIC,INTERNAL,PII_MED,PII_HIGH,PHI_HIGH - transforms:
DROP,REDACT_STABLE,TOKENIZE_REVERSIBLE,MASK_LAST4 - detectors:
FIELD_NAME,REGEX_EMAIL,REGEX_PHONE,NER_PERSON
You want every redaction to be explainable as: (field) + (detector) + (transform) + (policy_version).
Canonicalization first
Determinism starts with canonicalization. Same value, same normalization.
Examples:
- Emails: lowercase, trim whitespace
- Phone numbers: E.164 normalization
- Names: collapse multiple spaces, Unicode normalization
Skip this and you get nonsense like “John␠␠Smith” and “John Smith” producing two different placeholders. That breaks dedupe. It breaks tests. It also makes auditors cranky.
Stable placeholders that preserve retrieval utility
If you redact everything to ████, retrieval quality tanks and users hate you. Then product pushes to “just log a bit more context,” and you’re right back where you started.
Use structured placeholders instead:
{{EMAIL:sha256:9f2a...}}{{PERSON:sha256:1c0d...}}{{ACCOUNT_ID:sha256:ab91...}}
Why this works:
- It’s deterministic.
- It preserves type (EMAIL vs PERSON).
- It preserves equality (same email → same placeholder).
- It doesn’t leak the original value.
You can also do scoped determinism by salting per tenant:
placeholder = HMAC(tenant_salt, canonical_value)
That prevents cross-tenant correlation, which matters if you host multiple customers and don’t want “same email across tenants” to become an accidental join key.
A practical checklist (6 items)
This is the step-by-step I use when I’m wiring this into a real pipeline:
- Define field schema and sensitivity levels (start with 10–30 fields, not 300).
- Canonicalize values (email/phone/address/id) before any hashing/tokenization.
- Generate stable placeholders using HMAC (tenant-scoped) and include field type.
- Ensure only redacted text goes into chunking + embeddings.
- Store
policy_versionandtransform_versionin vector metadata. - Emit audit events at each stage with
doc_id,content_hash, and outcome counts.
If you’re also doing RAG over unstructured docs, treat “free text” as a field too. It’s the field that bites you.
How to implement reversible tokenization (token vault)
Reversible tokenization is where people do something unsafe like “encrypt the PII and store it in the vector DB.” Don’t.
A token vault is a separate system with:
- an API for
tokenize(value)anddetokenize(token) - strict authZ (RBAC/ABAC)
- hard rate limits
- immutable audit logs
- encryption at rest with envelope encryption (KMS/HSM)
The whole point is separation. The retrieval system shouldn’t be the same system that can re-identify users.
Random tokens vs format-preserving encryption (FPE)
Two common options:
-
Random tokens: generate
tok_...identifiers; store mapping in vault DB.- Pros: simplest, least leakage.
- Cons: loses format (email no longer looks like email).
-
Format-Preserving Encryption (FPE): output keeps the same character class/length.
- Pros: preserves downstream validators.
- Cons: more complexity; must be implemented correctly.
My stance: default to random tokens unless you have a hard compatibility reason for FPE.
Access controls: “break-glass” detokenization
If detokenization is easy, someone will use it “just to debug one thing.” That’s how policies die.
Make detokenization:
- restricted to a specific service identity (not developer laptops)
- gated by an approval workflow (HITL) for high-sensitivity classes
- time-bound (session TTL)
This pairs nicely with AI security controls. You want “can retrieve” and “can detokenize” to be separate permissions.
Vault retention
Tokens should have retention policies too.
- PII tokens: 30–90 days (example)
- PHI tokens: as short as your product allows
- Delete on user request: immediate, with propagation
If you keep tokens forever, you’ve built a permanent re-identification system. You just gave it a nicer name.
Retention windows, TTLs, and deletion propagation
Teams love redaction. Auditors love deletion.
You need explicit retention for every artifact:
- Raw docs (object store): e.g., 7–30 days
- Redacted docs: e.g., 90–365 days depending on policy
- Chunk store: same TTL as redacted docs
- Embeddings / vector rows: TTL aligned with redacted docs, but enforced by the DB
- Prompt logs: ideally 0 retention or hours/days, not months
- Caches (embedding cache, retrieval cache): short TTL (minutes to days)
This is where a lot of RAG systems fail “right to be forgotten” requests. They delete the raw doc and forget the embeddings.
Deletion propagation strategy:
-
doc_idis your primary key across all stores. - Every derived artifact carries
doc_id+content_hash. - A delete request emits a tombstone event.
- Consumers delete from blob store, vector DB, caches, and token vault.
- You log completion per store.
I’ve built RAG systems that handle millions of queries daily with sub-second responses, and the uncomfortable lesson was this: the fastest pipelines are usually event-driven ones. A deletion workflow that runs through the same event backbone as ingestion is the only way I’ve seen it stay reliable at scale.
If you want to do this cleanly, model the pipeline as a set of versioned data products, not a pile of scripts someone is afraid to touch.
Auditing & evidence: logs, controls, and leakage tests
“Trust us” doesn’t pass SOC 2, ISO 27001, HIPAA, or an internal security review. You need an evidence package.
1) Immutable audit log events
Every stage should emit an append-only record. Example fields:
timestampdoc_id-
content_hash(e.g., SHA-256) policy_versiontransform_versions- counts:
fields_redacted,tokens_issued,chunks_written,vectors_written -
operator/service_identity
If you already have OpenTelemetry instrumentation for AI agents or a logging schema, integrate with it. But be strict. Traces should carry metadata, not raw payloads.
2) Leakage test suite (CI-gated)
I’m going to be blunt: if you don’t have CI tests for leakage, you don’t have a privacy program. You have wishful thinking.
Your leakage suite should include at least:
-
Canary strings: inject unique strings like
CANARY_RAG_2026_9b1d...into sensitive fields and confirm they never appear in:- embeddings input
- vector DB payloads
- prompts
- logs
- Prompt injection retrieval tests: adversarial prompts that try to coerce the system to reveal secrets (especially via retrieved context). If you’re not already running prompt injection regression tests, start with How to Do Prompt Injection Regression Testing [2026 CI].
- Membership inference smoke checks: not academic perfection, just checks that sensitive canaries aren’t discoverable through retrieval or “search-like” queries.
A good target metric is: 0 canary exposures per 1,000 adversarial prompts in CI, plus a periodic run in staging or prod shadow.
For a more complete harness design, use RAG Data Leakage Test Suite [2026]: CI Red-Team Setup. This post is the privacy plumbing that makes those tests pass.
3) Controls matrix (auditor-friendly)
Map your implementation to controls they already recognize. Example rows:
- Data minimization: redaction before embedding
- Access control: vault detokenization RBAC + break-glass
- Retention: TTLs on vector rows + prompt logs
- Change management: policy versioning + approvals
- Monitoring: leakage test results stored and reviewed
If you can’t show change control, auditors assume your pipeline is mutable chaos. And honestly, they’re usually right.
Handling prompt injection that tries to retrieve secrets from the index
Redaction reduces what’s in the index. It doesn’t eliminate the attack.
Do all three:
- Index only redacted content (non-negotiable).
- Retrieval guardrails: blocklist patterns, sensitivity-aware filtering, and allowlists for which doc classes can be retrieved per user.
- Adversarial testing: keep a growing corpus of injection prompts and run them as regressions.
If you’re building agentic retrieval flows, also read Agent-Specific Attack Surfaces Security [2026]: What AppSec Misses and AI Agent Memory Exfiltration: Kill Chain + 5-Step Hardening [2026].
One data anchor (from my own shipped systems)
On the Walmart conversational commerce chatbot I worked on, we saw a 400% product engagement lift while serving millions of queries daily with sub-second responses. The lesson that matters here is not “use a better model.” At that scale, retrieval quality dominated answer quality.
Redaction that destroys retrieval utility will get rolled back under product pressure. It always does. Stable, typed placeholders are the compromise that actually survives contact with reality.
And if you care about cost, remember: retries and regeneration dominate the bill. Anything that causes more “I couldn’t find it” responses will quietly inflate your LLM cost.
Internal implementation map (so you can keep reading)
If you’re building the broader platform around this:
- For lifecycle + retention strategy: Data Privacy in RAG Redaction and Retention [2026 Playbook]
- For observability without leaking payloads: How to Pick LLM Application Observability Metrics [2026] and AI Agent Observability Logging Schema [2026]: OTel + Redaction
- For agent governance: AI Security Leader Playbook [2026]: 10 Controls That Ship
The bar in 2026 isn’t “we added a regex.” It’s “we can prove, repeatedly, that sensitive data doesn’t end up in the places it shouldn’t.”
If you implement the contracts and actually run the leakage tests in CI, privacy reviews stop being a blocking event. They become a gate you pass. Then you can go back to building useful things.
Originally published on kunalganglani.com
Top comments (0)