Layered detection, running on the device.
Every prompt is checked in the browser before it's sent anywhere. Cheap, deterministic checks run first, and the expensive ones only kick in when they're actually needed — so detection costs milliseconds, not a round trip to a server.
How the pipeline is ordered
Layers run cheapest first. Most prompts are already resolved by the time the expensive layers would kick in, which is what keeps typing latency untouched.
- L1Normalise + regex< 5msShipped
Unicode folded, encodings decoded, then structured identifiers: Aadhaar, PAN, cards, SSN, AWS keys, secrets.
↓ Most prompts resolve here — the rest continue - L2Heuristics< 10msShipped
Pattern families rather than fixed strings — instruction override, jailbreak framing, injection carriers, source code.
↓ Known attack shapes resolve here — the rest continue - L3On-device ML< 25msNot shipped
A quantised transformer via ONNX Runtime Web, for what the first two layers cannot settle. Implemented and tested; switched off until a real model backs it.
↓ still ambiguous - L4Custom detectorsvariesNot shipped
Per-tenant term lists and document fingerprinting.
↓ still ambiguous - L5Cloud escalation200–800msShipped · opt-in
Amazon Nova Pro on Bedrock for the genuinely ambiguous tail. Off by default, and fails open.
Order is the whole design. Deterministic checks are cheap, private and exact, so they run first and settle the majority. Only what survives reaches a layer that costs milliseconds or a network call — which is why detection adds latency you cannot feel, and why a prompt normally never leaves the machine at all.
What detects today
Implemented, tested, and running in the extension right now.
Personal data
- Email addresses
RFC-shaped addresses in free text
- Phone numbers
US formats (E.164 and common local forms)
- US Social Security numbers
Context-gated to cut false positives
- Credit card numbers
Luhn-validated, so a random 16-digit string doesn't trip it
- Aadhaar numbers
Verhoeff checksum-validated, with context matching for partial or mistyped numbers
- PAN (Permanent Account Number)
Structural validation against the real holder-type codes, so a random SKU doesn't trip it
Secrets and credentials
- AWS access keys
Access key IDs and STS session tokens
- Generic high-entropy secrets
Bearer tokens, API keys, private key blocks
Prompt attacks
- Direct prompt injection
Instruction override and jailbreak phrasing
- Indirect prompt injection
Instructions smuggled inside pasted or retrieved content — HTML comments, embedded role markers, text addressed at “the AI”
- Encoding evasion
Base64, hex, and zero-width character tricks used to slip past literal matching
- Prompt-leak attempts
Requests aimed at extracting a system prompt
Content and code
- Source code
Recognises code pasted into a prompt
- Harmful content
Heuristics over categories a policy may want to hard-block
- Model response scanning
Inbound direction, not just outbound prompts
What doesn't detect yet
Listed just as plainly as what's shipped. If you're evaluating us against something on this list, it isn't met today — full stop.
On-device ML classifier
The inference code, tokenizer abstraction, and fail-open wiring are implemented and unit-tested (transformers.js running an ONNX model). It stays disabled until a real model is provisioned — we would rather ship nothing than ship a classifier that returns a fixed answer.
Named entity recognition
The same on-device approach (transformers.js + an ONNX token-classification model), for personal data that regex fundamentally cannot catch — names, organizations, locations. Implemented and unit-tested; stays disabled until a real model is provisioned, same as above.
Non-US phone formats
Phone detection is US-format today. Indian and EU formats are next.
Read the code
The detection core is an Apache-2.0 licensed package in our monorepo. Every detector on this page is a file you can open, and every claim above is checkable against it. That's deliberate — in security tooling, “trust us” isn't an argument.
Next: how policies act on detections