
How to Redact PII Before Sending Data to an LLM (CPF, Phone, Email)
Step-by-step guide to redact PII before sending data to an LLM: mask CPF, phone and email, know where regex fails, and when to use a PII detector.
Want to apply this in your company?
Book a call with Juan →How to Redact PII Before Sending Data to an LLM (CPF, Phone, Email)
To redact PII before sending data to an LLM, put a layer between the source of the text and the model. That layer detects Brazilian CPF numbers (the individual taxpayer ID), phone numbers and email addresses, and swaps them for placeholders such as [CPF_1]. Regex with validation handles fixed formats well, but it fails on messy text, audio transcripts and personal names, where a dedicated detector helps. The central rule is to keep the mapping table outside the model and to test the layer with real messages before you trust it.
Key takeaways
- Masking hides the data, pseudonymization replaces it with a reversible placeholder, and true anonymization means there is no way back. Each option serves a different use.
- Regex with check-digit validation works well for CPF, CNPJ (the company tax ID) and email, and only reasonably well for phone numbers.
- Text typed by humans, transcribed audio and OCR output break patterns. In those cases you need a dedicated detector or a second check.
- The table that links each placeholder to the original value lives in a system your company controls, never in the prompt or in logs sent to the vendor.
- You measure the quality of the layer with a test set of real (already cleaned) messages, focusing on what slipped through, not on what was masked unnecessarily.
Masking, pseudonymizing or anonymizing: what is the difference?
The three terms are used as synonyms in meetings, but they have different effects. Choosing the wrong one creates a false sense of security.
Masking means hiding part of the data, for example showing only the last two digits of a CPF. It is useful for displaying information to a person, but it still leaves clues, and the rest of the text may identify the individual.
Pseudonymizing means replacing the data with a consistent placeholder, such as [CPF_1] or [EMAIL_2], and storing the mapping separately. The model can still reason ("customer [EMAIL_1] asked for a duplicate copy") and your application can reverse the swap in the reply. Under the logic of LGPD, Brazil's data protection law, pseudonymized data can still be linked to a person by whoever holds the additional information, so it still requires care.
Anonymizing means removing any reasonable possibility of identifying the person, with no table to go back. For free text this is hard, because a name, job title, city and the context of the conversation can all identify someone. In practice, most LLM projects settle on well-done pseudonymization, which already cuts exposure a great deal. Confirm the legal classification with whoever handles privacy in your company, since the final answer depends on the case.
What Brazilian data usually shows up in text?
Before writing any rule, take an inventory of what actually reaches the model. In WhatsApp support, email and web forms, the most common items are:
- CPF and CNPJ, with or without punctuation, sometimes with spaces in the middle.
- Phone numbers, with area code, with the leading 9 of mobile numbers, with +55, with parentheses, or stuck to another number.
- Email addresses, the most regular format of all.
- Full name, street address, postal code (CEP), date of birth and RG (the national ID card number).
- Pix keys, which can be a CPF, phone number, email address or random key.
- Order numbers, tracking protocols and license plates, which are not always personal data but are easy to confuse with it.
This inventory also defines what the model does not need to receive. To summarize a complaint, the CPF is almost never necessary. To look up an order, the CPF lookup should happen in a deterministic tool inside your application, not inside the prompt.
How far regex goes and where it fails
Regex is the right starting point: cheap, fast, auditable and able to run locally. But each type of data has a limit.
CPF: the 000.000.000-00 format is easy to capture, but the pattern alone produces false positives, because any sequence of eleven digits looks like a CPF. The fix is to validate the two check digits and discard repeated sequences (such as all digits being equal). That cuts false hits considerably. What regex does not catch: a CPF written out in words, with letters in the middle, with a space or line break between blocks, or with a digit mistyped by the customer (which fails validation and escapes, even though it is still nearly complete personal data). For that second situation, add a looser rule: if the sequence has the format but fails validation, mask it anyway. It is better to err on the side of protection.
Phone: this is the most ambiguous. Protocol numbers, tracking codes and amounts can be the same length as a mobile number. Use context (a plausible area code, the leading 9 on mobile numbers, the +55 prefix, nearby words like "whatsapp" or "call me") and accept that some cases will be doubtful. In customer support, ask which error costs more: masking a protocol number needlessly usually costs less than letting a phone number through.
Email: regex works well for normal addresses. It fails on versions written to dodge filters, such as "john at company dot com", which are common in informal chat.
Name and address: regex does not solve this. There is no pattern for a name, and name lists produce false positives on common words ("Rose", "Victoria", "Mercy"). This is the territory of dedicated detectors.
Text coming from audio or images: a transcript can contain "my cpf is one two three dot four five six". A numeric regex sees nothing. If you transcribe audio, read the article on transcribing WhatsApp voice messages with AI, because redaction has to run after transcription and, ideally, on the transcript itself.
When to use a dedicated PII detector
A dedicated PII detector combines rules, validators and entity recognition models to find what regex cannot reach, mainly names, addresses and data described in natural language. Open source libraries exist for this, such as Presidio, which lets you build custom recognizers (for example, one for CPF with validation). Check the official documentation of whichever tool you choose for real support of Brazilian Portuguese, since this varies by version and by the language model used inside it.
A simple decision guide:
- Only email, CPF and CNPJ in form fields: regex with validation is enough.
- Phone numbers in free text: regex with context, plus review by sampling.
- Names, addresses, or health and financial data in free text: a dedicated detector, plus testing with real messages.
- Audio, images or scanned PDFs: transcription or OCR first, then detection, and an extra check, because OCR errors become detection errors. The article on extracting data from PDFs with AI covers that review step.
- Sensitive data in large volume: consider not sending it to an external vendor at all and running a local model inside your own infrastructure.
A detector also makes mistakes. It is a second safety net, not a certificate that the text is clean. So the golden rule is to combine layers: regex for what has a format, a detector for what depends on context, and access limits for the rest.
Step by step: building the redaction layer
This is a roadmap that works for a support agent, an email automation or an internal tool.
- Map the flow: where the text comes from, where it goes, who sees the prompt and which logs store the content. Include the model vendor and the place where it processes data.
- Define what the model needs to know: for each task, list which fields are indispensable. Everything else stays out.
- Write the detection rules: regex with validation for CPF, CNPJ, email and phone, plus a detector for names and addresses when the task calls for it.
- Swap in consistent placeholders: the same CPF always becomes [CPF_1] within the conversation. Do not use fake data that looks real, since it may coincide with a genuine document.
- Keep the table outside the model: in your application's database or vault, with restricted access and a defined retention period. If you need a stable identifier across conversations, use a keyed function (HMAC) instead of a plain hash, because the space of CPFs and phone numbers is small and ordinary hashes can be reversed by guessing.
- Reverse only on output, and only when needed: the application replaces placeholders with the real data in the reply to the customer, after validating the content. See also guardrails for AI agents for checking the output.
- Apply the same cleaning to logs: masking the prompt is pointless if the log stores the original message with the same vendor.
- Test with a set of real messages that have already been cleaned, or synthetic ones, including the messy ones, and record what slipped through. Review the rules whenever the flow changes.
Illustrative scenario: a WhatsApp message
Illustrative scenario: a store receives the message "Hi, I'm Marina Souza, my cpf 123.456.789-09, my order never arrived. Call me on (11) 91234-5678 or marina@example.com.br". Before it reaches the model, the layer produces: "Hi, I'm [PERSON_1], my cpf [CPF_1], my order never arrived. Call me on [PHONE_1] or [EMAIL_1]".
The model summarizes the problem and drafts the reply. To look up the order, the application uses the real CPF, kept in the table, in a call to the store's system, without passing through the model. In the reply to the customer, the application reinserts the first name only if the text requires it.
Now a variation: the customer writes "cpf 123 456 789 09" and then "my whatsapp is eleven nine twelve thirty-four...". The first case can be caught by a rule that tolerates spaces. The second cannot. This kind of message belongs in your test set, and the design decision is what to do when the layer is unsure: mask, ask the customer to rewrite, or hand off to a human agent.
Where LGPD comes in
LGPD does not forbid using an LLM with personal data, but it requires purpose, necessity, security and transparency. Redacting before sending serves the necessity principle: the model receives only what it needs. It does not replace the legal basis, the notice to the data subject or the contract with the vendor. If the vendor processes data outside Brazil, read about international data transfer with AI providers under LGPD. The ANPD, Brazil's data protection authority, publishes guidance and is the primary source on the topic. For data leakage risks in LLM applications, the OWASP Top 10 for LLM Applications is a good technical reference, and the NIST AI Risk Management Framework helps organize risk management.
The method we use in this kind of work follows four steps. Map the flow and the baseline: which data circulates today and where. Limit data and actions: the model receives the minimum and executes nothing irreversible. Pilot a real flow, with logs and an agreed success metric, including the rate of data that escaped the layer. Hand over the operation with documented rules and decide whether to expand, adjust or stop.
Frequently asked questions
Can I rely on regex alone to protect CPF and phone numbers? For CPF, with digit validation, regex is good, but it does not cover variations written in words, mistyped digits or audio transcripts. For phone numbers, the ambiguity with other numbers is greater. Use regex as a first layer and test with real messages before depending on it.
Is pseudonymization the same as anonymization under LGPD? No. With pseudonymization there is a table or key that lets you get back to the person, so the data may still be considered personal. Anonymization requires that identification not be reasonably possible. Ask your legal team or data protection officer to validate the classification.
Does the model get worse when it receives placeholders instead of the data? For most support, summarization and classification tasks, the model works well with consistent placeholders, because what matters is the problem being described. When the task depends on the data itself, such as validating a CPF, do it in deterministic code outside the model.
Do I also need to redact logs and test data? Yes. Logs with the original message cancel out the benefit of the layer, and test data containing real information widens exposure. Apply the same cleaning to logs, set a retention period and use synthetic data in tests whenever possible.