DEV Community

Manu Shukla
Manu Shukla

Posted on • Originally published at ecorpit.com

Redact PII before it reaches the LLM: a 2026 DPDP-ready build guide

Redact PII before it reaches the LLM: a 2026 DPDP-ready build guide

Summary. Once a prompt leaves your network for a hosted model, you no longer control where the personal data inside it is logged, cached, or used for evaluation. That is the problem this guide solves in code. The fix is a redaction layer that sits in front of every model call, detects personal data, and replaces it before the request crosses your boundary. Under India's Digital Personal Data Protection Act 2023, a failure of "reasonable security safeguards" that leads to a breach carries a penalty of up to 250 crore rupees, with a separate 200 crore ceiling tied to children's data and breach notification, and the DPDP Rules were notified on 13 November 2025 with full substantive compliance due by 13 May 2027. Three engines do the detection work in production: Microsoft Presidio (open source, self-hosted), Amazon Comprehend PII detection (managed, priced at 0.0001 dollars per 100-character unit), and Amazon Bedrock Guardrails sensitive information filters (inline, block or mask). This is a build guide, not a policy memo: detection code, India-specific patterns for Aadhaar, PAN and GSTIN, reversible tokenization so you can re-identify safely, and the latency and cost you should budget for.

The threat is not exotic. It is the ordinary path a support ticket, a medical note, or a KYC record takes when your application pastes it into a prompt. The DPDP Act engineering playbook for Indian startups covers the wider obligations; here we go one layer down, to the request that carries a customer's phone number into a third-party model.

Why redaction has to happen before the model call

The controls most teams reach for first, a data processing agreement and a "we don't train on your data" toggle, are contractual, not technical. They do not stop the personal data from being transmitted, and they do not remove it from provider-side request logs, abuse-monitoring pipelines, or the memory of a sub-processor. Data minimization is a legal principle, not a preference. Section 6 of the DPDP Act limits consent, and therefore processing, to the personal data that is necessary for the stated purpose. The EU GDPR states the same idea in Article 5 and requires appropriate security under Article 32. The US HIPAA Safe Harbor method defines de-identification as the removal of 18 categories of identifier. Sending a raw customer record to a model when a redacted version would do the same job is the kind of over-collection all three regimes are written against.

The security framing is just as direct. The OWASP Top 10 for LLM Applications lists sensitive information disclosure as risk LLM06, and the cheapest mitigation is to never let the sensitive token reach the model in the first place. Redaction at the boundary turns "raw personal data leaving our perimeter" into a deliberate, logged exception rather than the default behaviour of every feature that calls an LLM.

There is an engineering payoff too. A redaction layer gives you one place to enforce policy across every model and every feature, instead of scattering ad-hoc string replacements through the codebase. It is the same reason teams put a prompt-injection guardrail in front of AI agents: a single, testable control point beats fifty inconsistent ones.

The architecture: a redaction gateway in front of every call

The pattern is a proxy. Every model request in your system routes through one service, and that service runs four steps.

  1. Detect. Run the prompt through a PII detection engine that returns the entity type, the character span, and a confidence score for each match.
  2. Substitute. Replace each detected span with either an irreversible placeholder (<PERSON>) or a reversible token that maps back to the original through a vault or an encryption key.
  3. Call the model with the redacted text.
  4. Re-identify, if needed. On the way back, swap the tokens in the model's response for the real values, so the end user still sees "Priya" and the real order number, while the provider only ever saw tokens.

Steps 2 and 4 are the difference between a redaction system that destroys utility and one that preserves it. If you replace an order ID with <NUMBER>, the model cannot answer "what is the status of my order," because you deleted the key it needed. Reversible tokenization keeps a stable, meaningless stand-in in the prompt and restores the real value in the answer.

Put this control at the gateway, not inside each feature. Tools such as the open-source LiteLLM proxy already support a Presidio pre-call hook, which is a practical way to add masking to a fleet of models without touching application code.

Detection engines compared

The three production choices trade control against operational load. Regex alone is a fourth option and it is not enough on its own, because names, addresses, and free-text identifiers do not follow fixed patterns.

Engine Where it runs Detection method Reversible? Indicative cost Best for
Microsoft Presidio Self-hosted (your VPC) Regex + spaCy NER + checksum Yes, via encrypt or a vault map Compute only Data residency, custom entities, full control
Amazon Comprehend PII Managed AWS API Managed ML model No (detect and mask) 0.0001 dollars per 100-char unit, 300-char minimum Fast start, no model to maintain
Bedrock Guardrails filter Inline with Bedrock Probabilistic, context-aware ML No (block or mask) Priced with Bedrock usage Teams already on Bedrock
LLM Guard Anonymize Self-hosted scanner Presidio-based + patterns Yes, with a vault Compute only Input and output scanning in one library
Raw regex Anywhere Pattern only Yes Negligible Structured IDs only, never names

Microsoft Presidio is the default when data cannot leave your environment. Its analyzer combines regular-expression recognizers with a spaCy named-entity-recognition backend and checksum validation, and its anonymizer offers replace, redact, mask, hash, and encrypt operators. Because the encrypt operator is reversible, Presidio also ships a companion deanonymizer for controlled re-identification. Amazon Comprehend removes the model-maintenance work: its PII endpoints either check whether personal data is present or locate and redact it, at 0.0001 dollars per 100-character unit with a three-unit minimum per request. Amazon's own documentation describes the Bedrock Guardrails sensitive information filter as "a probabilistic machine learning (ML) based solution that is context-dependent," which is the honest way to say it will not catch everything and must be tested against your data.

Build it with Presidio

Install the analyzer and anonymizer, plus a spaCy model for the NER backend.

pip install presidio-analyzer presidio-anonymizer
python -m spacy download en_core_web_lg
Enter fullscreen mode Exit fullscreen mode

Out of the box Presidio recognizes global entities such as PERSON, EMAIL_ADDRESS, CREDIT_CARD, and PHONE_NUMBER. It does not know Indian identifiers, so add them as pattern recognizers. These regexes match the published formats: PAN is five letters, four digits, then a letter; Aadhaar is a 12-digit number, often written in three spaced groups; GSTIN is 15 characters; IFSC is four letters, a zero, then six alphanumerics.

from presidio_analyzer import AnalyzerEngine, PatternRecognizer, Pattern

india = [
    PatternRecognizer(supported_entity="IN_PAN",
        patterns=[Pattern("pan", r"\b[A-Z]{5}[0-9]{4}[A-Z]\b", 0.85)]),
    PatternRecognizer(supported_entity="IN_AADHAAR",
        patterns=[Pattern("aadhaar", r"\b\d{4}\s?\d{4}\s?\d{4}\b", 0.6)]),
    PatternRecognizer(supported_entity="IN_GSTIN",
        patterns=[Pattern("gstin", r"\b\d{2}[A-Z]{5}\d{4}[A-Z][A-Z0-9]Z[A-Z0-9]\b", 0.9)]),
    PatternRecognizer(supported_entity="IN_IFSC",
        patterns=[Pattern("ifsc", r"\b[A-Z]{4}0[A-Z0-9]{6}\b", 0.8)]),
    PatternRecognizer(supported_entity="IN_UPI",
        patterns=[Pattern("upi", r"\b[\w.\-]{2,256}@[a-zA-Z]{2,64}\b", 0.4)]),
]

analyzer = AnalyzerEngine()
for r in india:
    analyzer.registry.add_recognizer(r)
Enter fullscreen mode Exit fullscreen mode

The Aadhaar score is deliberately low, at 0.6, because any 12-digit run matches the shape. In production you raise confidence with the Verhoeff checksum Aadhaar uses, and you set a confidence threshold so a raw invoice number does not get masked as an identity number. That tuning, false positives against false negatives, is the real work; the regex is the easy part.

Now anonymize reversibly, so the model sees a token and you can restore the real value afterward.

from presidio_anonymizer import AnonymizerEngine, DeanonymizeEngine
from presidio_anonymizer.entities import OperatorConfig

KEY = "a-32-byte-key-from-your-kms-not-here"  # fetch from KMS at runtime
anonymizer, deanonymizer = AnonymizerEngine(), DeanonymizeEngine()

def redact(text: str):
    results = analyzer.analyze(text=text, language="en")
    out = anonymizer.anonymize(text=text, analyzer_results=results,
        operators={"DEFAULT": OperatorConfig("encrypt", {"key": KEY})})
    return out.text, out.items  # tokens in text; items map spans back

def restore(text: str, items):
    return deanonymizer.deanonymize(text=text, entities=items,
        operators={"DEFAULT": OperatorConfig("decrypt", {"key": KEY})}).text
Enter fullscreen mode Exit fullscreen mode

Wrap the two functions in a gateway so every feature gets the same control. The pattern below redacts on the way in and restores on the way out, and it is where you attach audit logging: record the entity types and counts you removed, never the raw values.

from fastapi import FastAPI, Request
app = FastAPI()

@app.post("/v1/complete")
async def complete(req: Request):
    body = await req.json()
    safe_prompt, items = redact(body["prompt"])
    # log {"entities": [i.entity_type for i in items]} — never the raw text
    model_answer = call_model(safe_prompt)      # provider sees only tokens
    return {"answer": restore(model_answer, items)}
Enter fullscreen mode Exit fullscreen mode

Encryption is the reversible route when you do not want a separate store. The alternative is a tokenization vault: replace each value with a random token and keep the token-to-value mapping in a database your application controls, so the mapping never travels with the prompt. Use encryption when statelessness matters and irreversible redaction, a plain <PERSON> placeholder, when the model never needs to refer back to the value.

Reversible vs irreversible: pick per field

Not every field should be reversible. A name in a summarization task can be redacted to <PERSON> and never restored, because the summary does not need it. An order ID in a support agent must be tokenized reversibly, because the agent has to look it up. Decide per entity type, not once for the whole prompt.

Requirement Technique Restores original? Notes
Model never needs the value Redact or replace No Cheapest; highest privacy
Model must reference it later Encrypt operator Yes, with the key Stateless; key lives in KMS
Cross-request stable mapping Tokenization vault Yes, via lookup Mapping stays in your database
Analytics on masked data Hash No Same input maps to same hash
Keep field shape for the model Format-preserving token Yes Preserves length and type

Format-preserving tokens matter more than they look. If a model is asked to validate a 10-digit phone number and you replace it with <PHONE>, the model's reasoning about digit count breaks. A stand-in that keeps the shape, a fake but well-formed number, keeps the task intact while the real number stays home.

India-specific considerations

If you process the data of people in India, the DPDP Act 2023 makes you a data fiduciary with duties that do not disappear when a third-party model does the processing on your behalf. The Act received presidential assent on 11 August 2023, and the Ministry of Electronics and Information Technology notified the DPDP Rules on 13 November 2025, with the substantive obligations, consent notices, breach notification, and Significant Data Fiduciary duties, due by 13 May 2027. The penalties are structured by failure type: up to 250 crore rupees for inadequate security safeguards that lead to a breach, up to 200 crore for a failure to notify or to protect children's data, and up to 150 crore for unmet Significant Data Fiduciary obligations.

Two practical consequences follow for the redaction layer. First, your India identifier recognizers, Aadhaar, PAN, GSTIN, UPI virtual payment addresses, and IFSC codes, are not optional add-ons; they are the specific data your users will paste. Second, data residency shapes the build-versus-buy call: a self-hosted Presidio deployment inside an India region keeps detection entirely within your boundary, while a managed detector is another processor to account for. Teams cleaning up historic exposure should pair this with the guidance in DPDP legacy data remediation and consent backfill, and connect the runtime control to a DPDP consent manager so redaction and consent state stay aligned.

Latency, cost, and the failure modes that bite

A redaction layer is not free, and pretending otherwise is how it gets ripped out under load. Budget for three costs.

Latency. NER inference adds milliseconds per request, and it grows with prompt length. Keep the spaCy pipeline warm, run detection on the input concurrently with any retrieval you are already doing, and cache results for identical inputs. For very long documents, chunk and detect in parallel rather than serially.

Money. With Amazon Comprehend at 0.0001 dollars per 100-character unit and a 300-character minimum, a 2,000-character prompt costs 20 units, or 0.002 dollars, per detection call. That is trivial per request and real at millions of requests a day, which is exactly the volume that also makes a self-hosted Presidio worth its operational weight. Model the two curves before you commit.

Correctness. False negatives leak; false positives destroy utility. A missed Aadhaar number defeats the whole control, while an over-eager recognizer that masks every 12-digit invoice number makes the assistant useless. Tune confidence thresholds against a labelled sample of your real prompts, add checksums where the identifier has one, and treat the output filter as a second line: Bedrock Guardrails, for instance, will not detect PII returned inside a tool-use function-call parameter, so a model that echoes personal data through a tool call can bypass an output-only filter. Detect on input and output, and log every redaction so you can prove what left your perimeter and what did not.

Build vs buy: the honest decision

Reach for a managed detector (Amazon Comprehend or Bedrock Guardrails) when you want to ship this quarter, you are already on AWS, and your volumes are moderate. Reach for self-hosted Microsoft Presidio when data residency is a hard requirement, when you need custom India recognizers with checksums, or when request volume makes per-call pricing the larger cost. Most teams end up with both: Presidio in the request path for control and custom entities, and a managed filter as a backstop on model output. The enterprise AI agent governance approach treats redaction as one layer in a stack, alongside consent, retention, and access logging, not a single box to tick.

FAQ

What counts as PII you must redact before an LLM call?

Any data that identifies a person: name, email, phone, address, government IDs such as Aadhaar and PAN, financial identifiers like IFSC codes and UPI addresses, and health or biometric details. Under the DPDP Act 2023, all of this is personal data, so the safe default is to detect and mask it before the prompt leaves your network.

Is Microsoft Presidio or Amazon Comprehend better for redaction?

They fit different needs. Presidio is open source and self-hosted, so detection stays in your environment and you can add custom India recognizers. Amazon Comprehend is a managed API at 0.0001 dollars per 100-character unit with no model to maintain. Choose Presidio for residency and control, Comprehend for a fast managed start.

Can I get the original value back after redaction?

Yes, if you choose a reversible technique. Presidio's encrypt operator lets a companion deanonymizer restore values with the key, and a tokenization vault keeps a token-to-value mapping in your own database. Use reversible tokens when the model must reference a value later, and irreversible redaction when it never needs the original.

Does redaction make me DPDP compliant?

No single control makes you compliant. Redaction supports the data-minimization duty in Section 6 and the security-safeguard duty whose breach can cost up to 250 crore rupees, but DPDP also requires consent, notice, breach notification, and retention limits. Redaction is one necessary layer in that stack, not the whole obligation.

How much latency does a redaction gateway add?

Detection adds milliseconds that scale with prompt length, driven mainly by the NER pass. Keep the model warm, run detection concurrently with retrieval, cache identical inputs, and chunk long documents for parallel scanning. At typical prompt sizes the overhead is small; the real risk is unbounded latency on very long inputs, which chunking controls.

Will a regex-only approach work for PII detection?

Only for structured identifiers with fixed formats, such as PAN, GSTIN, or IFSC. Regex cannot reliably find names, addresses, or free-text personal data, which is why Presidio pairs regexes with a spaCy NER model and checksums. Use regex for India ID formats and named-entity recognition for everything unstructured, together, not alone.

What happens if the model returns PII in its answer?

Filter output as well as input. A model can echo personal data, and some filters miss it: Amazon documents that the Bedrock Guardrails filter will not detect PII inside a tool-use function-call parameter. Run detection on responses too, restore only the tokens your user is entitled to see, and log every redaction event for audit.

Where should the redaction layer live in my stack?

At a single gateway that every model request passes through, not inside each feature. A proxy such as LiteLLM can run a Presidio pre-call hook so masking applies across every model without changing application code. One control point is testable, auditable, and consistent, which fifty scattered string replacements never are.

How eCorpIT can help

eCorpIT builds the privacy layer into AI applications for teams that cannot afford to leak personal data into a third-party model. We design detection-and-redaction gateways with Microsoft Presidio, Amazon Comprehend, or Bedrock Guardrails, add India-specific recognizers for Aadhaar, PAN, GSTIN, and UPI, and wire in reversible tokenization, audit logging, and retention controls aligned with DPDP Act 2023 requirements. As a Gurugram-based, CMMI Level 5 and ISO 27001:2022 certified engineering organisation, our senior-led teams ship this as production infrastructure, not a prototype. To scope a redaction layer for your stack, contact us.

References

  1. Microsoft Presidio (open-source PII detection and anonymization)
  2. Presidio anonymizer operators (replace, redact, hash, encrypt)
  3. Presidio supported entities
  4. Amazon Comprehend: detect PII entities (documentation)
  5. Amazon Comprehend pricing
  6. Amazon Bedrock Guardrails: sensitive information filters
  7. Amazon Bedrock Guardrails (product overview)
  8. LiteLLM: Presidio PII masking tutorial
  9. OWASP Top 10 for LLM Applications (LLM06 sensitive information disclosure)
  10. DPDP Rules 2025 notified (Press Information Bureau)
  11. Navigating data minimization under India's DPDP Act (S&R Associates)
  12. Digital Personal Data Protection Rules, 2025 (overview)
  13. EU GDPR Article 32 (security of processing)
  14. HIPAA Safe Harbor de-identification (US HHS)

Last updated: 1 August 2026.

Top comments (0)