FDE PulseFDE jobs open 641New in 7 days 47Companies hiring 98Remote-friendly 24%Median US pay $203kTop hirer Databricks 122
VI

The newspaper of the Forward Deployed Engineer

Tools

Microsoft Presidio: masking PII before you call an LLM, and why its own documentation won't promise to catch it all

This open-source library gives you a personal-data filter that sits in front of the model. Out of the box it ships only English models, and it says plainly that it will miss things.

Microsoft Presidio: masking PII before you call an LLM, and why its own documentation won't promise to catch it all
Photo: Christina Morillo / CC0
ShareLinkedInFacebookX

In brief

  • Presidio has an Analyzer (detection with NER and regex) and an Anonymizer (replace, redact, mask, hash, encrypt).
  • By default it ships only English models and recognizers, and it lacks the national identifiers of many countries.
  • No warranty, no SLA, and an API with no authentication: you have to wrap it and measure it yourself.
Three-box diagram: the app sends raw text to a gateway running Presidio, which sends PII-masked text to the model provider. On the return path, an orange arrow reads "PII unscanned": the output_parse_pii flag only restores tokens to their original values. A callout linked to the arrow gives the fix: set presidio_filter_scope to output or both.
With Presidio at the gateway, PII is masked on the way out, but LiteLLM's output_parse_pii flag only swaps tokens back to original values; it does not scan the model's response. Source: LiteLLM and Presidio documentation, as cited in the article.

Presidio’s documentation contains one sentence every FDE should read before plugging it into a customer’s system: there is no guarantee that Presidio will find all sensitive information. A library built to mask personal data admits that it will miss some. Understanding that admission is the first step to using it properly.

When you build an agent or chatbot on top of support tickets, patient records or customer email, the first question from the security team is usually: does personal data leave for the model provider?

Presidio is an open-source tool for answering that question. But if you simply install it and nod that “PII is masked”, you are promising something its own authors will not.

What Presidio does, in two modules

Presidio started as the microsoft/presidio repository and has since moved to data-privacy-stack/presidio, with documentation now at presidio.dataprivacystack.org. The project describes itself as modules for identifying and anonymising private entities in text and images, released under the MIT licence.

The first module is the Analyzer. It runs a set of recognizers, each detecting one or more PII types with its own mechanism: an NER model, regex, or other logic. It ships with global entities such as credit card numbers, email addresses, IP addresses, URLs, PERSON, LOCATION and PHONE_NUMBER, plus some country-specific types for places such as the US, the UK, Singapore and Thailand.

The second module is the Anonymizer, which decides what to do with what was found. Its operators are replace, redact, mask, hash, encrypt and custom. Encrypt alone is reversible, using the deanonymizer’s decrypt operator with the same key, so you can mask data before sending it to the model and then restore the original values for the user.

What happens when a ticket goes through Presidio?

Picture a bank customer submitting a ticket written in Vietnamese: full name, email address, card number and an internal customer ID in the form “KH-482913”. The email and card number follow fixed patterns, so Presidio’s regex will most likely catch them. The name is another matter.

The default NER model is spaCy’s en_core_web_lg, an English model. The documentation states that by default only English recognizers and models are provided; supporting another language means extending both the NLP engine and the recognizers, and each language can use only one NER model. A Vietnamese name in the middle of a Vietnamese sentence can easily slip past an English model.

The ID “KH-482913” will certainly get through, because no built-in recognizer knows it. The default entity list also lacks the national documents of many countries, such as Vietnam’s citizen ID card or tax code. The fix is to write a PatternRecognizer: a regex for the ID format, plus context words such as “customer ID” and validation logic if needed.

A detail that is easy to forget: context words depend on language. English context words applied to Vietnamese text are close to useless. And regex catches only what has a pattern: if a support agent types the ID in the wrong format, say without the hyphen as “KH482913”, a regex written for “KH-482913” will not recognise it.

The return path is where teams forget

A common deployment puts Presidio at the gateway layer, masking PII before a request reaches the model provider; the official samples page includes an example of doing exactly this with an AI gateway. LiteLLM also has a guardrail that uses Presidio, but you must deploy both the Analyzer and Anonymizer containers yourself.

The trap lies in LiteLLM’s output_parse_pii flag. The documentation is clear that it only swaps masked tokens back to their original values after the model call; it does not run PII detection on the response. To scan the response as well, you must set presidio_filter_scope to output or both.

One more thing the customer’s security team will ask about: Presidio’s API endpoints have no built-in authentication, by design. You have to put them behind an authentication layer in your infrastructure; otherwise the PII-masking service becomes an open door to the very PII it is meant to protect.

Knowing the limits is what lets you sell it

Presidio’s FAQ says plainly that all detection logic makes errors, and that reducing false positives comes at the cost of more misses.

It also acknowledges that SaaS PII services often cover more entities or are more accurate, and that Presidio is not an official product of any company, with no warranty and no SLA.

The documentation therefore recommends adding other layers of protection.

When presenting to a customer, put Presidio in its proper place: one layer among several, backed by measured numbers.

Before the demo, hand-label a sample of the customer’s real text, run it through the pipeline, and report how many entities slipped through, by type.

When customers see that you found the gaps yourself first, they trust you more than they would a promise that “everything is masked”.

A sensible learning order: get to grips with the Analyzer and Anonymizer on English text, then write a PatternRecognizer for a customer-specific identifier, then try configuring the NLP engine for another language, and finally deploy behind an authenticated gateway that scans both directions.

On a CV, a line such as “built a PII-masking layer in front of an LLM, measured the miss rate on a labelled data sample, wrote recognizers for internal identifiers” shows employers that you understand deployment with real data, not just calling an API.

Customers will not ask whether you use Presidio. They will ask what still leaks out, and you should be the one with an answer in numbers.

Was this article useful?

Use with your AI assistantAsk Claude ↗Ask ChatGPT ↗
10 sources
Read next on the roadmap · Stage 5: DeploymentDatadog for FDEs: tracing a slow request to the right log line on a customer's systemIf a log line is missing its trace_id field, the investigation stalls in the middle of a customer meeting. The check that catches the problem takes five minutes.