The short version
You type something into ChatGPT. Veil intercepts that text, runs it through a fast local detection pipeline, and marks anything sensitive right where you wrote it — before you send. The entire detection happens on your machine. Nothing travels anywhere.
What Veil is watching
Veil runs as a Chrome extension with a content script that attaches to the page. It monitors textarea elements and contenteditable divs — the kind you find in Gemini’s input box, Notion, Claude.ai, and anywhere else where you type into a rich-text field.
Every time you pause typing, the current text goes into the detection pipeline. The pause threshold is intentionally short — you shouldn’t have to wait to see the highlights appear.
The detection pipeline
Step 1 — Regex pre-scan
The first pass happens instantly, with no model involved. Veil has a set of built-in regular expressions that catch PII with a predictable, structured format:
| Pattern | Example |
|---|---|
| Email address | sarah@company.com |
| Phone number | (415) 555-0187 |
| Social Security Number | 482-66-1209 |
| OpenAI API key | sk-proj-... |
| AWS access key | AKIA... |
| JWT token | eyJ... |
| IPv4 address | 192.168.1.1 |
These fire synchronously. By the time the text reaches the model, you’re already seeing some highlights.
Step 2 — GLiNER2 NER model
For PII that depends on context — a person’s name buried in a paragraph, an organisation mentioned in passing, a street address written out in plain English — Veil sends the text to a local HTTP server running on 127.0.0.1:8765.
That server runs a GLiNER2 named-entity recognition model. It’s a transformer-based model designed specifically for this kind of span detection, and it runs on your CPU or GPU depending on what’s available. The 127.0.0.1 binding is not a setting you can misconfigure — it’s loopback-only, unreachable from anywhere outside your device.
The entities GLiNER2 detects:
- PERSON — names, including partial names
- LOCATION — cities, countries, specific places
- ORGANISATION — companies, institutions, teams
- ADDRESS — full or partial street addresses
- DATE_OF_BIRTH — birth dates in various formats
Step 3 — Merge and deduplicate
Regex and model results come back independently. Before rendering, Veil merges the two sets of spans and resolves any overlaps — if a regex match and a model match cover the same characters, the higher-confidence detection wins. The merged result is then rendered as inline highlights directly inside the input field.
Redaction modes
There are two ways to handle detected PII once you see the highlights:
Anonymize replaces each unique value with a consistent alias — <PERSON_1>, <PERSON_2>, and so on. The same person mentioned twice gets the same alias. This is useful when the structure of the text matters and you want the AI to reason about relationships without knowing the actual names.
Mask replaces PII with a type label: [NAME REDACTED], [SSN REDACTED]. Simpler, more aggressive. Good when you just want the sensitive data gone.
You can switch between modes in the Veil popup, and you can redact individual spans by clicking them or redact everything at once with a single button.
Architecture overview
Browser tab (content.js)
│ raw text on every input event
▼
Background service worker (background.js)
│ POST /detect
▼
Local Python server — GLiNER2 (127.0.0.1:8765)
│ JSON array of detected spans
▼
background.js — merge regex + model results
│ final span list
▼
content.js — apply inline highlights to the DOM
The local server is the only network hop in the whole pipeline, and it’s bound to loopback. There is no path by which your text reaches the internet during detection.
Privacy guarantees
Veil was built on a few hard commitments:
- No cloud detection. The only server Veil talks to for detection is the one running on your own machine. If that server isn’t running, Veil falls back to regex-only detection — it doesn’t fall back to a cloud API.
- No telemetry. There’s no analytics library, no crash reporter, no usage tracking. Veil doesn’t know how many people use it or what they type.
- No sync. Any settings or API keys you configure are stored in
chrome.storage.local. Chrome’s sync engine doesn’t touch it. - Open source. The entire codebase is on GitHub. If you want to verify any of the above, you can read the code.
Supported sites
Veil works on any site with a textarea or contenteditable input. These have been explicitly tested:
| Site | Input type | Status |
|---|---|---|
| ChatGPT | contenteditable |
✅ Supported |
| Claude.ai | contenteditable |
✅ Supported |
| Google Gemini | contenteditable |
✅ Supported |
| Any site | textarea |
✅ Supported |
| Firefox | — | 🔜 Planned |