Card numbers
The Luhn check digit and the card issuer range, whether the groups are split by spaces, dashes or dots.
Detection engine
Once people learn to click through a warning, every dashboard still looks healthy and nothing is protected. Itzal’s detection runs on the employee’s own device, and each layer narrows what the next has to judge, so a warning still means something when it appears.
Worked example
A support engineer pastes a ticket into an AI tool to draft the reply. The card number and the IBAN are caught by their check digits, the Stripe key by the prefix Stripe puts on it, and the customer’s name by the label in front of it.
The decision is made on the laptop. Your console gets the finding types and a masked snippet, never the ticket.
| Found | Layer | What confirmed it | Reported under |
|---|---|---|---|
| Customer name | Context | The field label “Customer:” in front of two capitalised words | GDPR, CCPA |
| Card number | Patterns | The Luhn check digit, then the card issuer range | PCI DSS |
| IBAN | Patterns | The length fixed for a UK IBAN, then the mod-97 check | GDPR, CCPA, GLBA, Internal |
| Stripe secret key | Patterns | The literal prefix Stripe puts on live secret keys | Internal |
How it works
The cheap, certain checks run first and the expensive, uncertain ones run last, on what is left. All of it happens on the device, and none of the text is sent anywhere to be classified.
Invisible characters are stripped, and full-width digits, Arabic-Indic, Devanagari and Thai numerals, and Cyrillic or Greek look-alike letters are folded to plain ones. This happens on a copy that keeps a map back to the original, so a mask always covers the bytes that were actually typed. A long base64 run is decoded one level and scanned again.
Every pattern compiles to an automaton that runs in time proportional to the length of the text and never backtracks, so no paste can stall it. Each match is then held to whatever check its format allows: Luhn and the issuer range for a card, the country length and mod-97 for an IBAN, the scheme’s own checksum for an identity number, the vendor’s literal prefix for a credential.
“SSN:” directly before nine digits is strong evidence, and “invoice” or “order number” nearby counts against them, though for less when the value passed a checksum. When the text is a table, the header row is read once and applied to every cell in its column, however far down the sheet the value sits.
A zero-shot entity model (GLiNER small) ships inside the installer and runs in its own helper process, apart from the agent that holds the device certificate. It finds names written plainly in a sentence, where no title or label announces them, and the entity types you describe in your own words.
Every finding carries the frameworks it falls under, and the policy for each says what happens: record it, warn, block, or redact the values and let the rest go. When a message holds several findings, the strictest action wins. The agent makes that call against a signed policy, not the browser extension.
A check that runs out of time lets the message go, and says so. If detection has not answered 250 ms after someone presses send, the message is released rather than freezing their work. The scan finishes anyway and the event is marked as having missed its deadline, so a slow check never shows up in the console as a clean one. Text beyond 1 MB is cut off and the event is marked as truncated.
What it recognises
Each one is held to the check its format allows. Where a number has no check of its own, it is reported only with its label nearby, so a nine-digit order number is not read as somebody’s identity.
The Luhn check digit and the card issuer range, whether the groups are split by spaces, dashes or dots.
IBANs by their country length and mod-97. A US routing number only with an account number and a label beside it, since a routing number alone is a published bank code.
Social Security area rules plus the words nearby. A bare nine-digit run with no label is deliberately not reported.
UK National Insurance, Spanish DNI and NIE, Italian codice fiscale and French NIR by their own checks. Canadian SIN, Indian Aadhaar and Dutch BSN with their label nearby.
Indian PAN on its own. Australian TFN, German Steuer-ID, UK NHS and Australian Medicare numbers with their label nearby.
Private keys, keys and tokens from AWS, GitHub, OpenAI, Anthropic, Google, Slack, Stripe, npm, PyPI, SendGrid and Azure storage, JWTs, and connection strings with a password in them.
Email addresses and North American phone numbers. A phone number on its own ranks as low severity.
Names after a title or a field label, names in plain prose through the on-device model, and postal addresses.
The same engine reads what is inside a file. Text taken out of Word, Excel, PowerPoint and PDF attachments goes through every layer above, and so does the text in a pasted screenshot where text-in-images is switched on. Anything that cannot be read is recorded as unread, never as clean.
Framework mapping
An SSN is tagged HIPAA only when health words sit near it, and FERPA or GLBA only near academic or financial ones. Tagging every SSN with all three would give you a compliance filter that matches everything, which tells an auditor nothing.
Any card number that passes its checks, wherever it appears. A card number needs no context to be cardholder data.
A name, an address or an SSN beside words like patient, diagnosis or prescription. UK NHS and Australian Medicare numbers always.
Names, addresses, email, phone numbers, SSNs and IBANs. Identity numbers issued outside the US count under GDPR only, because CCPA is a California law.
See it on your own policy
Forty-five minutes with an engineer, against the frameworks you actually answer to.
Book a demoAlso mapped
A framework here is a set of detectors and an action, not a certificate. What it finds, and what it does when it finds it, is yours to set.
Accuracy
Every detector has its own precision target, set by how bad its errors are. A checksum-validated card number should almost never be wrong. A name found from context gets more room on recall, and none on precision, because its mistakes are the ones people see and learn to dismiss.
The on-device name model, measured the way a device runs it
precision on names, against a target of 0.80
recall on the same corpus, against a target of 0.85
false positives per 100 KB of clean prose, against a budget of 5
| Detector | Precision target | Where it stands |
|---|---|---|
| Card numbers | 0.99 or better | Luhn alone measured 0.976, because build numbers that start with a year pass it by chance. That is why the issuer-range check exists. |
| US routing plus account number | 0.98 or better | 1.00 precision and recall on its corpus. That is a floor on what the corpus thought to test, not a field result. |
| Names, on-device model | 0.80 or better | 0.959, after a capitalisation rule removed lower-case role phrases such as “the team lead”. Before that rule and a higher threshold, it was 0.604. |
| US Social Security numbers | 0.95 or better | Below target 0.88 on English text, and 0.71 once reference numbers labelled in six other languages are added, because the words that count against a match are English only. Your own context words are the fix. |
| International phone numbers | 0.85 or better | Not switched on Written and measured at 0.59, almost entirely switchboard numbers in email signatures, so it stays off. |
These figures come from a synthetic corpus that our own team wrote. They show where each detector stands against its target, not what it will score on your traffic. In a live deployment the number we watch is how often people click through a warning: above 30%, they have learned it is noise. A log-only pilot gives you your own figures before anything warns or blocks.
Evasion
Each of the tricks on the right beat the detector completely when the test suite was first written. They are now caught, and a test fails if any of them stops being caught.
SSN 123 - 45 - 6789
SSN 123-45-6789
MTIzLTQ1LTY3ODk=
Spaced-out separators, full-width digits, and the same number in base64. All three are read as the SSN they are. Invented data.
Caught today
Not caught yet
It is built to stop mistakes, not a determined insider. Someone set on getting data out can photograph a screen. We say so plainly so that you size your other controls on what this actually does.
Your own rules
Case numbers, project codenames and claim handlers are not in anybody’s built-in list. You add them in the console, and they reach every device in your organisation with the next policy update.
A pattern rule
P-234987, CH-2024-88213, PROJ-ACME. Matched inside the same 250 ms check as the built-in detectors, so it can warn, block or redact with no wait.
An entity type
Describe it in up to 40 characters, such as “patient name” or “claim handler”, and the on-device model is asked for it by name. Nothing is trained.
Your vocabulary stays with your organisation. The words you add to put an identifier in a framework’s domain (a health system adds patient, diagnosis and prescription) reach only your own devices. Rules are stored encrypted, are never written to a log, and nothing you tune flows back into the detectors other customers run.
On the roadmap
Not available yet
None of these is in the product today. They are listed so you can plan around them rather than discover them.
Straight answers
Including the ones where the honest answer is a limit.
There is no single number. Each detector has its own precision target, from 0.99 for card numbers to 0.80 for names, and the measured figures are published on this page, including the ones below target. Your own rate comes from a log-only pilot on your own traffic.
No. It ships inside the installer and runs on the device, in a helper process kept apart from the agent, because the agent holds the device certificate and a large native library reading untrusted text does not belong beside it. No text is sent anywhere to be classified.
From a synthetic corpus full of values that look sensitive and are not, and from the false-positive dispositions your analysts record in case management, which carry a reason and the already-masked snippet. There is no button for sending us a misclassified sample, and there will not be one.
No. The check runs in a small program on the device, and the raw text is never transmitted, stored off the device, or written to a log. Your console receives finding types, frameworks and the action taken.
No. An SSN is tagged HIPAA only when health words such as patient or diagnosis are near it, and FERPA or GLBA only near academic or financial words. Your administrators can add their own words to each list.
Yes, in two ways. A pattern rule matches anything with a shape, such as a case number, inside the normal check. An entity type is a phrase like “claim handler” that the on-device model is asked for by name, so the category can be one no training set contains.
If the check has not answered 250 ms after someone presses send, the message is released rather than held. The scan still finishes and the event is marked as having missed its deadline, so the console never mistakes a timeout for a clean result.
Plenty, and we publish it rather than wait to be asked. Coverage is reported per surface and the uncovered ones are named. Surface coverage.
Read next
Detection can only judge the text it is handed. The coverage page names the browsers, apps and files that hand it text, and the ones that do not.
Which browsers, apps and file types the engine is handed text from, and which ones it is not, named per surface.
See what is coveredThe questions that separate one AI DLP product from another, starting with where classification physically runs.
Read the guideBook a demo
Measure it against your own prose
Forty-five minutes with one of our engineers. A log-only pilot then measures your real false-positive rate on your own traffic, before anything warns or blocks.
Book a technical demo