StatusCompleted
PriorityHigh
Has UIYes
Sourcerich

Doc Sanitizer

A local Flask app that strips sensitive terms out of a document before it goes to an LLM, then puts them back afterward.

01 — THE PROBLEM

Any time you paste a client contract, a course brief with a company’s real name in it, or an internal doc into ChatGPT or Claude, that content leaves your machine. For a solo consultant that’s already uncomfortable when the material has client names, IBANs, fiscal codes, or project IDs in it. At company scale it’s the same problem multiplied: employees pasting internal docs into consumer LLM tools is one of the most common ways sensitive data leaks outside a company’s boundary, and most “AI usage policy” documents are just a plea not to do it, with no tool backing the rule up.

I built this because I kept hitting the same friction: I wanted an LLM’s help rewriting or analyzing a document, but the document had real company names, people, IBANs, or IDs in it that I didn’t want in a prompt history I don’t control.

02 — THE APPROACH

It’s a local web app (Flask, runs at localhost:5001, no cloud, no accounts) with two modes switchable from the top nav. Single file mode: upload a .docx/.pptx/.xlsx or any text file, the app extracts the text and scans it with a set of built-in regex detectors — emails, UUIDs, capitalised name-like sequences, IBANs, Italian fiscal codes, VAT numbers, phone numbers, alphanumeric IDs like PRJ-0042 — plus any custom regex you add. You review each candidate, edit it to set the exact canonical form, then confirm or dismiss it into a persistent dictionary (term → token, e.g. “Acme Corp” → “__TERM_1__”). Hit obfuscate and it swaps every dictionary term in the document for its token, case-insensitively, and you can search the sanitised output right there in the tool to confirm nothing slipped through before you copy it out. Once the LLM hands back its response, you paste or upload the file back in and rehydrate — tokens are swapped back for the real terms, restored to the exact form you stored, and the office file keeps its original formatting.

The second mode, folder batch, does the same thing across an entire directory tree at once: point it at a folder, it walks every file, shows one deduplicated list of candidate terms found across all of them, and after you review, writes sanitised copies to a sibling `<folder>_sanitised` directory (originals are never touched). After the LLM pass, you point rehydrate at that folder and it writes `<folder>_rehydrated`. That’s the part that makes it more than a single-document trick — it’s the same dictionary and token scheme applied at the scale of “here’s a whole project directory I need help with,” not just one file.

Underneath, the dictionary lives in SQLite, encrypted at rest with SQLCipher — the key is a generated 256-bit hex value kept outside git, and a corrupted key file fails hard rather than silently regenerating and orphaning the encrypted data. Tokens are monotonic and never reused, even after deletions, so a stale mapping can’t silently collide with a new term.

03 — WHAT I LEARNED

The harder problem wasn’t detection, it was reversibility with fidelity. Regex-flagging “this looks like a name or an IBAN” is the easy 80%; making sure the exact original casing and formatting comes back afterward, inside a .docx or .pptx without breaking the document’s formatting, took real care — substitutions go into the first text run of a paragraph and later runs get cleared, otherwise Word’s run-splitting silently strips the token before it can be found and replaced back. I also learned to treat “case-insensitive match, canonical restore” as an explicit design decision rather than a bug: a document that says “ACME” and “Acme” both round-trip to whatever form is in the dictionary, and that’s the correct behavior once you decide the dictionary — not the document — owns the canonical spelling.

04 — WHERE THIS COULD GO

The pattern generalizes past “protect my own documents”: any team piping internal content through an LLM API or tool needs the same obfuscate-before-send, rehydrate-after step, just automated instead of manual. The dictionary-of-terms-to-tokens approach is the same idea behind enterprise DLP (data loss prevention) tooling, just scoped to the LLM boundary specifically rather than email or file uploads generally — and most companies don’t have that scoped version yet. A natural next step is wiring this in as a proxy layer in front of an LLM API call rather than a manual copy-paste tool, so obfuscation and rehydration happen automatically around every request instead of requiring a human in the loop for each document.

05 — TAKEAWAY

A small, deliberately unambitious local tool that solves a real and recurring problem — keep sensitive terms out of LLM prompts without losing the ability to get LLM help on the document — beats hoping you remember to redact things by hand.

Text summarized and optimized using Anthropic’s models and reviewed by a human.