How I Measured the PII Layer in Front of an LLM (And Version One Masked the Label, Not the Tax Number) Microsoft Presidio's default English NER pipeline misidentified a Greek tax number (ΑΦΜ) as an organization label, masking the words 'tax number' while allowing the actual number to pass through to logs, according to Petros Savvakis's first installment of his 'From Prompt to Proof' series ahead of his PyCon Greece 2026 talk. The failure occurred silently with HTTP 200, highlighting that compliance controls must be measured, not assumed. Savvakis's testing showed the English pipeline tagged the Greek phrase 'ζητάει προσφορά' as a person at 85% confidence and scored the tax number as US identifiers at 5%, below typical thresholds. - Published on How I Measured the PII Layer in Front of an LLM And Version One Masked the Label, Not the Tax Number - Authors - Name - Petros Savvakis @PetrosSavvakis https://twitter.com/PetrosSavvakis How I Measured the PII Layer in Front of an LLM And Version One Masked the Label, Not the Tax Number PII masking, GDPR, AI Act, "just put Presidio in front of it"... those are some of the keywords that come up every time someone talks about putting an LLM in a real-world system. All of that is valid, of course. The question is what it actually looks like when you stop treating it as a checkbox that works and start measuring it. This is Part 1 of 7 of a series I'm calling From Prompt to Proof . I'll be publishing it on the blog before my PyCon Greece 2026 talk a repo with all of this will be available soon , because the talk is 30 minutes and the interesting bits the numbers, the mistakes, the "wait, that silently does nothing" parts do not fit in 30 minutes. The series is about the control plane around an LLM feature and around AI agents: identity, PII, policy as code, human in the loop, signed audit, tracing. The working example in the repo is QuoteBot, a small loan pricing assistant the same patterns apply to insurance, healthcare, and anything else that is regulated . Every layer is a real package with tests. If a box on the architecture diagram has no package behind it, it's a claim, not a control. Part 1 is Layer 2: mask before the model. And measure the masker, or you don't have one. The failure that started this A colleague pasted a customer record into a support prompt, because that's what the box is for. No attack mode yet One paste and a Greek tax number ΑΦΜ is now sitting in a US inference log. That's a personal data transfer to a third country, and it didn't need a hacker. So I put a detection layer between the request handler and the model client. Version one of that layer produced this: Ο πελάτης με