Area 06 // AI SecurityLesson 96 / 14014 min read
PII redaction and data leakage
PII redaction removes or replaces personal details (names, emails, phone and card numbers) before text reaches a model, logs or a third party, and data-leakage prevention stops private information escaping through answers, prompts, logs, caches or training data.
Think of it like this
Analogy
A hospital sends patient files to an outside lab. Before they leave, a clerk blacks out names and addresses and writes a case number instead. When results come back, the clerk matches the case number to the patient. The lab does its job without ever learning who the patient is. And the hospital also checks its own filing cabinets, photocopiers and bins, because files leak from those too.
The problem it solves
Users paste emails, phone numbers, card details and medical information into chatbots. That text then flows into a provider's API, your logs, traces, caches, analytics, eval datasets and perhaps fine-tuning data. Each copy is a privacy risk and a compliance problem (GDPR and similar laws). Meanwhile the model itself can leak: repeating its hidden prompt, other users' data from a shared cache, or confidential documents from RAG.
How it works: PII redaction
- Decide what counts as PII for you: names, emails, phone numbers, addresses, ID numbers, card and bank numbers, health data, and so on.
- Detect with a mix of methods: patterns and checksums for structured data (cards, IBANs), named-entity models for names and addresses (as of November 2026, Microsoft's open-source Presidio is a common choice), and custom recognisers for your own IDs.
- Redact or pseudonymise: replace values with typed placeholders (
<EMAIL_1>), keep the mapping in a short-lived vault, and restore values in the reply only when the user should see them. - Apply it everywhere data flows: before the model call, before logging and tracing, before storing eval or training data.
- Test it on realistic samples in your languages and formats; measure misses and over-redaction.
How it works: data leakage
- Map leakage paths: model answers, hidden prompts and context (OWASP hidden context exposure), logs and traces, semantic and response caches, RAG indexes, vector stores, provider data retention, fine-tuning data, and third-party tools the agent calls.
- Minimise: send the model only what the task needs; don't put secrets or other users' data in prompts (token budgets help here too).
- Scope by user and tenant: retrieval filtered by permissions (RAG access control), caches keyed by tenant (semantic caching).
- Detect leaks: canary tokens in hidden prompts, output scanners for PII and secrets, red-team tests (red teaming).
- Control the provider side: check data-retention settings, zero-data-retention options, regions, and whether your data is used for training.
- Limit retention in your own systems: delete logs and conversations on a schedule; support user deletion requests.
See it in code
- Needs
- Nothing: plain Python 3. Production systems use a detector such as Presidio instead of three regexes.
Reversible redaction with placeholders, plus a canary-token leak check.
import re
# PII REDACTION with reversible placeholders: the model never sees the real values; we restore them after.
PATTERNS = {
"EMAIL": r"[\w.+-]+@[\w-]+\.[\w.]+",
"CARD": r"\b(?:\d{4}[ -]?){3}\d{4}\b", # check cards before phones (both are digit runs)
"PHONE": r"\+?\d[\d -]{8,}\d",
}
def redact(text: str):
vault, counter = {}, {}
for label, pattern in PATTERNS.items():
for value in re.findall(pattern, text):
counter[label] = counter.get(label, 0) + 1
token = f"<{label}_{counter[label]}>"
vault[token] = value
text = text.replace(value, token)
return text, vault
def restore(text: str, vault: dict) -> str:
for token, value in vault.items():
text = text.replace(token, value)
return text
msg = "Hi, I'm Sam (sam.lee@example.com, +44 7700 900123). Card 4111 1111 1111 1111 was charged twice."
safe, vault = redact(msg)
print("sent to model :", safe)
reply = "Thanks! We'll refund the duplicate charge and email <EMAIL_1> a receipt."
print("shown to user :", restore(reply, vault))
# DATA LEAKAGE test: plant a canary in the hidden prompt and check that outputs never contain it.
CANARY = "canary-7f3a"
system_prompt = f"[{CANARY}] You are a support bot. Internal discount code: STAFF50."
leaky_output = "My instructions start with [canary-7f3a] You are a support bot..."
print("leak detected :", CANARY in leaky_output)sent to model : Hi, I'm Sam (<EMAIL_1>, <PHONE_1>). Card <CARD_1> was charged twice.
shown to user : Thanks! We'll refund the duplicate charge and email sam.lee@example.com a receipt.
leak detected : TrueThe name "Sam" got through: regexes can't find names, which is why real systems add an entity-recognition model. The card number is a standard test number. Note the system prompt also contains a discount code: the real fix for that is to keep secrets out of prompts altogether.
A real example
Example
The traces that held everything
A health-insurance chatbot redacted PII before calling the model, and the team was proud of it. During an audit, they found their tracing tool recorded the raw user message before redaction, plus tool results containing policy numbers and diagnoses, all retained for a year and visible to the whole engineering team.
They moved redaction to the very first step of the request, added a redaction processor to the tracing pipeline, restricted trace access, cut retention to 30 days, and added a CI test that sends known fake PII through the app and asserts it never appears in logs, traces or the response.
The easy way
Start here
Run a PII detector (Presidio or your provider's tool) on every message before the model call and before logging, replace values with placeholders, and set log retention to the minimum you need. Add a canary to your system prompt and alert if it ever appears in an output.
When you grow: the production setup
Mature setups use a privacy layer shared by all AI features: entity detection tuned per language, reversible pseudonymisation with a secure vault, redaction in logs, traces and eval data, tenant-scoped caches and indexes, provider zero-retention agreements and regional processing, retention schedules and deletion workflows, leakage tests in CI, and privacy reviews for new data flows.
Trade-offs
What you gain
- Large reduction in privacy and compliance risk.
- Logs and traces become safe to share with more people.
- Placeholders keep conversations useful.
What it costs you
- Detectors miss some PII and over-redact other text.
- Redaction can remove context the model needed.
- Adds latency and another component to maintain.
When not to use it
- Don't redact data the task truly needs and the user consented to share (e.g. drafting a letter to a named person); minimise and protect it instead.
Common mistakes
- Redacting model input but logging the raw message.
- Regex-only detection that misses names and addresses.
- Putting secrets or other customers' data in prompts.
- Shared caches that serve one user's answer to another.
- Using raw customer conversations as fine-tuning data.
Interview questions
Try answering out loud first, then open the model answer.
How would you protect PII in an LLM application?
Model answer
Minimise what's collected and sent; detect PII with patterns plus entity models; replace with placeholders via a short-lived vault and restore only for the owning user; apply redaction before model calls, logs, traces, analytics and training data; scope caches and retrieval by user; configure provider retention and region; set retention limits; and test with seeded fake PII.
What are the ways data can leak from an LLM app?
Model answer
Through answers (other users' data via shared caches or unfiltered retrieval, memorised training data), hidden context exposure (system prompts, tool definitions), logs and traces, analytics and eval datasets, third-party tools and plugins, provider retention, and exfiltration via prompt injection (e.g. data encoded into URLs). Each path needs its own control.
What is a canary token and how is it used with LLMs?
Model answer
A unique random string planted in hidden content such as a system prompt or a confidential document. If it ever appears in an output, log or external request, you know that content leaked. It's cheap to add, works in automated tests and production monitoring, and helps measure prompt-extraction resistance.
Quiz
Pick an answer to see whether it’s right and why.
0 of 5 answered
Key terms
- PII (personally identifiable information)
- Data that can identify a person, such as names, emails, phone numbers, addresses, ID and card numbers. It must be protected and often masked.
- Redaction
- Removing or masking sensitive details such as personal data or secrets before text is sent, stored or shown.
- Pseudonymisation
- Replacing personal details with placeholders or codes (like EMAIL_1) while keeping a separate, protected mapping so the real values can be restored when allowed.
- Data leakage
- Private or confidential information escaping to people or systems that shouldn't have it, through answers, logs, caches, prompts or training data.
- Canary token
- A unique random string planted in hidden content (like a system prompt); if it ever shows up in an output or request, you know that content leaked.
Before and after
Progress is saved in this browser only.