Remove names, emails, API keys and passwords from any text before you paste it into ChatGPT. 100% in your browser, nothing is uploaded.
Paste your text, check what got hidden, then copy the safe version into ChatGPT (or anywhere). Your text never leaves the tab: no servers, no uploads, no API calls. The only download is the AI model itself, once. You can verify this: open your browser's Network tab and watch it stay empty while you type.
Live: tenzanlogic.com/paste-shield Built by Tenzan Logic
Pasting work text into ChatGPT leaks whatever was in it: customer names, invoice numbers, API keys, passwords. Server-side "redaction" tools just move the leak to their server. Paste Shield runs the entire pipeline locally, on a GPU you already own.
- Paste your text (or drop a
.txt/.md/.log/ ... file). An email, a log, some code, anything. - Private details get hidden. Names, emails, addresses, phones, dates, account numbers, keys and passwords become neutral placeholder labels (
{{PERSON_1}},{{EMAIL_1}}, ...), computed on your device. Spot-check each one and reveal any false match. - Copy or download the safe text. Paste it into ChatGPT or any tool; the placeholders read clearly and your data stays out.
You can also pin always-hide terms (client names, project codenames) that the model cannot infer.
Everything inside the dashed boundary runs in the browser tab. The only network egress is a one-time, cached fetch of the model weights.
flowchart TB
subgraph Tab["Browser tab (nothing leaves here)"]
direction TB
UI["page.tsx + PasteShieldApp<br/>React 19, App Router"]
subgraph Detect["Detection (on device)"]
direction LR
Regex["regex-secrets.ts<br/>structured credentials"]
Custom["custom-terms.ts<br/>always-hide list"]
Worker["privacy.worker.ts<br/>Web Worker"]
end
Merge["merge-entities.ts<br/>merge - dedup - redact"]
Store[("localStorage<br/>lang + custom terms")]
SW["service worker<br/>offline shell + ORT cache"]
UI --> Regex
UI --> Custom
UI --> Worker
Regex --> Merge
Custom --> Merge
Worker --> Merge
Merge --> UI
UI <--> Store
SW -.-> UI
end
Worker ==>|"model weights, once, then cached"| HF["huggingface.co<br/>AI model + ORT runtime"]
HF -.->|"cached in CacheStorage"| Worker
classDef egress stroke-dasharray: 4 4;
class HF egress;
A keystroke debounces through useDeferredValue, the cheap deterministic nets run instantly, and the model adds free-form PII once it is ready. The model never re-runs on text it has already seen (spans are cached by source string).
sequenceDiagram
participant U as User
participant App as PasteShieldApp
participant Det as regex + custom sweeps
participant W as privacy.worker
participant R as redact()
U->>App: paste / type
App->>Det: sweep(text)
Det-->>App: structured spans (instant)
Note over App: model not ready, so the result is rules-only and Copy stays disabled
App->>W: run(text) once ready
W->>W: chunk into windows, locate spans, drop mis-tags
W-->>App: model entities (or null sentinel on failure)
App->>R: redact(text, deterministic + model)
R-->>App: safe text + placeholder map
App-->>U: highlighted output, Copy unlocked
The worker reports a monotonic load percentage, then settles into one terminal state. It fails closed: an error sticks, and Copy stays disabled until the model is deliberately reloaded.
stateDiagram-v2
[*] --> lite: no WebGPU or under 4 GB RAM
[*] --> loading: capable device
loading --> ready: weights loaded
loading --> error: load failed (after q4f16 to q4, WebGPU to WASM, cache-wipe retries)
ready --> loading: Reload model
error --> loading: Reload model
lite --> [*]
note right of ready
Only "ready" unlocks Copy / Download.
"lite" runs the deterministic nets only,
which never substitute for the model.
end note
Three layers, all on device:
- Privacy AI model (free-form PII): names, emails, addresses, phones, dates, account numbers. Understands sentence context, so it finds values that have no fixed format. Runs in a Web Worker via
@huggingface/transformersv4 on WebGPU (required; WASM is only an automatic retry when a WebGPU adapter fails to initialize, and browsers without WebGPU get rules-only Lite mode). We keep every span (no confidence cutoff, since a miss is a leak) and flag low-confidence ones for review. - Deterministic regex net (structured credentials only): API keys, tokens, JWTs, private keys, IBANs, cards, keyword passwords. Runs instantly, even before the model loads, because the model's secret recall is unreliable and a leaked key is catastrophic. It is not a general rule layer: no URL or name rules; a deterministic email rule backstops the model while it loads and in Lite mode.
- Your always-hide list: words only you know are sensitive (client names, project codenames).
The model's spans are otherwise only cleaned: boundary-safe offsets, dropping numeric or @-less mis-tags, and protecting any {{LABEL}} you paste back in. Over-redaction is the safe side by design.
- No server-side inference, ever. No OpenAI / Anthropic / Gemini API. No user text crosses the network; the only fetch is the model weights, once.
- The model runs only in a Web Worker via
@huggingface/transformerson WebGPU (required; WASM is only an automatic retry when a WebGPU adapter fails to initialize, and browsers without WebGPU get rules-only Lite mode). - ONNX Runtime wasm is self-hosted (
public/ort) so a strict CSP keepsconnect-srclocked to Hugging Face only. - Cross-origin isolation headers (COOP / COEP / CORP) are required for the model runtime and set in both
next.config.tsandvercel.json. - Why
script-srcstill carries'unsafe-inline': replacing it with build-timesha256-...hashes of the inline scripts was attempted and aborted. Next.js embeds a random build ID in every inline RSC flight payload, so the hash set changes on every build of identical source (verified by hashing two consecutive builds), and hashes pinned invercel.jsoncould never match the build Vercel itself produces. Revisit if inline scripts become deterministic per commit, or via a nonce-based CSP (which would require dynamic rendering). - No analytics, no telemetry. The app ships no tracking of any kind.
The model needs WebGPU and roughly 4 GB of RAM. Without them the app says so honestly: there is no rules-only "safe to paste", because detection is the model or nothing.
Next.js 16 (App Router) · React 19 · TypeScript · Tailwind CSS v4 · @huggingface/transformers v4 · Web Workers · WebGPU · Vercel. Fully bilingual (English / Polski).
bun install
bun run dev # copies ORT wasm, then next dev
bun run test # vitest unit suite for the redaction/detection corebun run build runs the same ORT copy step before next build. The codebase is intentionally small (around 2k LoC); see AGENTS.md for the hard constraints every change must respect.
Built by Tenzan Logic, a software studio that ships and operates its own production demos.
Case study: tenzanlogic.com/en/portfolio/paste-shield/