Entity types¶
Every entity wardcat can detect, with the action it takes when you enable it
without naming one, and the layer that finds it. Detection is opt-in — a bare
Wardcat() detects nothing until you add_entity(...). The same list at the
prompt: wardcat entities [--layer regex|ner|llm]; in code:
Wardcat.supported_entities(layer).
Regex (built-in, no dependencies)¶
Financial & identity¶
| Entity | Default action | Description |
|---|---|---|
CREDIT_CARD |
hash |
Visa (13/16/19-digit), MasterCard (51–55 and the 2-series 2221–2720), Amex, Discover, Diners, JCB (3528–3589 and the legacy 15-digit 1800/2131), Maestro, Troy — with or without separators; Luhn (mod-10) validated |
IBAN |
hash |
International IBAN — mod-97 checksum validated |
SSN |
hash |
US Social Security Number (123-45-6789), or written without dashes after its label |
BANK_ROUTING |
hash |
US bank routing number (ABA / RTN) — mod-10 checksum over a Federal Reserve prefix |
CRYPTO_WALLET |
hash |
Bitcoin (Base58Check and bech32/bech32m segwit, both checksum-verified) and Ethereum-style 0x addresses |
NIN |
hash |
UK National Insurance Number (AB123456C) |
NHS_NUMBER |
hash |
UK NHS number — 10 digits, mod-11 checksum |
TC_ID |
hash |
Turkish national ID — 11 digits, whole or grouped, Nüfus İdaresi checksum validated |
EU_NATIONAL_ID |
hash |
Spanish DNI / NIE, French INSEE, Dutch BSN, Polish PESEL — each verified against its own check rule |
CODICE_FISCALE |
hash |
Italian tax code (RSSMRA85T10A562S) |
VAT_NUMBER |
warn |
EU VAT (DE/FR/GB/IT/ES/AT/NL prefixed) + Turkish Vergi No (keyword-based) |
PASSPORT |
hash |
Passport numbers — keyword-based (passport no:, pasaport, Reisepass, passeport) |
DATE_OF_BIRTH |
hash |
Birth dates — month names (TR/EN/DE/FR) or keyword + numeric/ISO date |
VEHICLE_PLATE |
warn |
Turkish vehicle plates (34 ABC 123) |
FINANCIAL_AMOUNT |
redact |
Monetary amounts (₺/$/€/£, 45.000 TL, 2.1 milyon TL) — off by default |
Contact & location¶
| Entity | Default action | Description |
|---|---|---|
EMAIL |
warn |
RFC-compliant email addresses |
PHONE |
warn |
Turkish (0, +90), French national (01 23 45 67 89), German mobile (0151 …), international E.164 (+1, +44, …), and any national format once it is labelled (Phone:, call me at …); other regions via with_phone_regions() |
ADDRESS |
warn |
Turkish (Cad., Sok., Mah.), English (Street, Avenue, Road…), French (Rue, Allée…), Spanish (Calle, Avenida…), Italian (Piazza, Corso…), Dutch (straat, gracht…), German (Straße, Weg, Platz…) |
POSTAL_CODE |
warn |
Turkish postal codes (01000–81999) |
UK_POSTAL_CODE |
warn |
British postcodes (SW1A 1AA, GU21 6TH, M1 1AE) |
US_ZIP_CODE |
warn |
US ZIP+4 codes (12345-6789) |
Network & technical¶
| Entity | Default action | Description |
|---|---|---|
IP_ADDRESS |
warn |
IPv4 addresses — the quad must stand alone, so a longer dotted run (03.93.92.16.85, a French phone number) is not read as an address |
IPv6 |
warn |
IPv6 addresses (full and compressed forms) |
MAC_ADDRESS |
warn |
Network hardware address (00:1A:2B:3C:4D:5E) |
IMEI |
hash |
Mobile device IMEI — 15 digits, Luhn-checked |
UUID |
warn |
RFC 4122 UUID / GUID |
USERNAME |
hash |
Account name introduced by its keyword — kullanıcı adı ahmet.yilmaz, username: jsmith42, login jdoe. Only the handle is taken |
JWT |
hash |
JSON Web Token (starts with eyJ) |
CUSTOM_SECRET |
hash |
API keys & tokens: OpenAI/Anthropic (sk-, sk-ant-), Stripe (sk_live_), AWS (AKIA), Google (AIza, ya29.), GitHub (ghp_, fine-grained github_pat_), GitLab (glpat-), Slack (xoxb-, webhook URLs), Twilio (SK/AC), SendGrid (SG.), npm (npm_), Hugging Face (hf_), Shopify, DigitalOcean, Azure storage keys, Sentry DSNs, connection-string passwords and PEM private-key blocks. Also a credential written into a sentence — parolası ise …, password is …, erişim kodu … — where the word beside it is the only evidence; only the value is taken, not the keyword |
HIGH_ENTROPY_STRING |
redact |
A run of 32+ base64-shaped characters with the Shannon entropy of a generated key, or a long hex digest — a secret with no known prefix and no keyword. Off by default, scored 0.70 under the default floor; see the regex layer |
SpaCy NER (requires wardcat[ner] + a language model)¶
| Entity | Default action | Description |
|---|---|---|
PERSON |
hash |
Person names (first + last) — cross-language |
ORG |
warn |
Organization / company names |
ADDRESS |
warn |
Street addresses and facilities (complements regex) |
LOCATION |
warn |
Countries, cities, regions and geographic features (spaCy GPE / LOC). These used to arrive as ADDRESS — enable this to keep covering them |
NRP |
redact |
Nationality, religious or political group — GDPR Art. 9 data. These used to arrive as ORG. Off by default: these are ordinary words |
NER requires an explicit model — there is no default
NER is off by default; calling with_ner() without a model (or language)
raises ConfigError. Choose a model in a documented way via language=
(recommended) or spacy_model=. Running, say, the Turkish model on German
text produces noisy results, so pick the model per language (or rely on the
LLM layer for cross-language names). A multilingual gazetteer filters out job
titles, HR terms, and abbreviations (EN/DE/FR/TR) that NER models commonly
mislabel. How to pick a language, a size tier and several models at once is
on the detection layers page.
LLM (requires an on-prem LLM backend)¶
| Entity | Default action | Description |
|---|---|---|
PASSPORT |
hash |
Passport numbers of any country — contextual detection (e.g. Passport: A12345678) |
EU_NATIONAL_ID |
hash |
French INSEE, German Personalausweis — contextual variants not caught by regex |
UK_POSTAL_CODE |
warn |
Postcodes in ambiguous contexts |
US_ZIP_CODE |
warn |
ZIP codes in ambiguous contexts |
CUSTOM_SECRET |
hash |
Contextual secrets — password=VALUE, api_key=VALUE, access codes |
SPECIAL_CATEGORY |
redact |
GDPR Art.9 special-category data — health, religion, ethnicity, political opinion, sexual orientation, trade-union, genetic/biometric. Off by default (semantic, LLM-only) |
| (any above) | — | LLM supplements and verifies all regex/NER entity types |
GDPR special categories
SPECIAL_CATEGORY flags sensitive statements that have no pattern — a stated
health condition, religious or political affiliation, or trade-union
membership — which only the LLM can detect. It is off by default; enable it
under llm_detector.entities. Because it is semantic and subjective, expect
lower precision than structural entities.
with_llm() brings its own default policy — most of these types switched on,
each with the action above — so a guard with the LLM layer detects more than
the entities you named. The configuration guide
shows how to take control of it.