What it looks for, and how it recognises each type
nullcipher runs 242 detectors: the rules described below, including 196 provider-key rules ported from the open-source scanner gitleaks. Each detector is a fixed rule, run in this order; when two rules overlap, the earlier one wins (a GitHub token inside token= is labelled as a GitHub token, not a generic secret). Checksums are used wherever the format has one, because false alarms matter too: a masked version number or order ID makes the AI's answer harder to use.
Each type has its own page with a live check and the provider's own revoke or rotate steps: what each kind of secret looks like, and what to do if you already pasted one into an AI. In the list of what was hidden, each type's name links to its page.
- Private key blocks — [PRIVATE_KEY_1]
- A whole
-----BEGIN … PRIVATE KEY-----to-----END … PRIVATE KEY-----block (RSA, EC, DSA, OpenSSH, PKCS#8, encrypted and PGP) becomes one placeholder. Public keys and certificates are left alone; they are meant to be shared. - AWS access key IDs — [AWS_KEY_1]
AKIA(long-term) orASIA(temporary) followed by exactly 16 upper-case letters or digits. The matching 40-character secret key has no prefix, so it is caught by the config rule when it sits afteraws_secret_access_key=.- GitHub tokens — [GITHUB_TOKEN_1]
ghp_,gho_,ghu_,ghs_orghr_followed by at least 36 letters and digits, or a fine-grainedgithub_pat_token.- Slack tokens — [SLACK_TOKEN_1]
xoxb-(bot),xoxp-(user),xoxa-orxoxr-followed by the dash-separated number and secret groups.- Stripe secret and restricted keys — [STRIPE_KEY_1]
sk_live_,sk_test_,rk_live_orrk_test_followed by at least 10 letters and digits. Publishablepk_keys are designed to be public and are not masked.- Google API keys — [GOOGLE_API_KEY_1]
AIzafollowed by exactly 35 letters, digits, dashes or underscores — 39 characters in all.- OpenAI and Anthropic API keys — [OPENAI_KEY_1] [ANTHROPIC_KEY_1]
sk-ant-plus at least 20 characters is Anthropic.sk-proj-,sk-svcacct-orsk-admin-plus at least 20 characters, or a legacysk-key of exactly 48 letters and digits, is OpenAI.- Discord bot tokens — [DISCORD_BOT_TOKEN_1]
- Three dot-separated base64 parts whose first part decodes to the bot's 17–20 digit Discord user ID, so a bot token is recognised without the word Discord nearby. More
- Wallet recovery phrases — [RECOVERY_PHRASE_1]
- 12, 15, 18, 21 or 24 consecutive words from the 2,048-word BIP-39 English list whose built-in SHA-256 checksum is valid (checked in this tab). Only 1 in 16 random 12-word runs passes, so a sentence made of list words stays; the whole phrase becomes one placeholder. More
- Keys and tokens from 196 more provider formats — [SENDGRID_API_TOKEN_1] [NPM_ACCESS_TOKEN_1] …
- Ported from gitleaks' default rules, each under its own placeholder: Slack webhook URLs, Twilio, SendGrid, npm, PyPI, Hugging Face, GitLab, Shopify, DigitalOcean, Heroku, Azure AD client secrets, Databricks, Doppler, Grafana, HashiCorp Vault, Linear, Notion, PlanetScale, Postman, Pulumi, Sentry and many more. Only the secret part is masked, and a rule runs only when its keyword appears. Where a provider's key has no prefix of its own (Mailgun, Telegram, Twitter, Discord client secrets), the rule needs the provider's name just before the value, as in
MAILGUN_API_KEY=…. - Google Cloud service-account key files — [GCP_SA_KEY_ID_1]
- The 40-hex-digit
private_key_id; the key file's private key is masked as a private key block and itsclient_emailas an e-mail address. More - JSON Web Tokens — [JWT_1]
- Three base64url segments joined by dots, where the first segment actually decodes to a JSON object with an
"alg"field. Domain names and file names with dots fail that decode, so they stay. - Passwords and keys in connection strings, URLs and commands — [CONN_SECRET_1]
- Only the secret part, so the AI can still help with the command: the password in
postgres://app:password@db:5432/orders(alsoredis://:password@host);Password=,AccountKey=andSharedAccessKey=in aKey=Value;connection string; thesig=of an Azure SAS URL and theX-Amz-Signature=of an S3 presigned URL; the password incurl -u user:password;--password VALUE(docker login,wget);mysql -pPASSWORD; and a.netrcpassword. Host, user, port, database,AccountNameand the other SAS parameters stay. Nothing to hide, so left as is:curl -u bob(curl prompts),mysql -p mydb(mysql prompts),--password-stdin, anddocker run -u 1000:1000. - Bearer tokens and Basic credentials — [BEARER_1]
- The token after
Authorization: Bearer(it must contain a digit, so the phrase “Bearer authentication” is left alone) and the base64 value afterBasicwhen it decodes touser:password. The header name and the scheme stay. - Session cookies — [COOKIE_1]
- Every value in a
Cookie:request header, in a raw HTTP dump, acurl -Hargument orcurl -b 'name=value', because a request's cookie list is session state and the session cookie can have any name. InSet-Cookie:only the first value. Cookie names and the attributesPath,Domain,Expires,Max-Age,Secure,HttpOnlyandSameSitestay readable. - Passwords and secrets in config lines — [PASSWORD_1] [SECRET_1]
- The value after a key whose last word names a secret —
password,passwd,pwd,pass,passphrase,secret,token,api_key,access_key,private_key,client_secret— inKEY=value,key: value,"key": "value"and--key=valueshapes. The key stays visible so the AI still understands the line. This includes a secret-named parameter in a URL query string, such as?api_key=…or&access_token=…, whilepage=andlang=stay. Left alone:true/false/null,${VAR}references, type names such aspassword: string, code such aspassword = get_secret(), keys liketoken_ttlormax_tokens, and the shell'sPWD=working directory. An unquoted value ends at the first space. - E-mail addresses — [EMAIL_1]
name@domain.tldwith a letters-only top-level domain.user@localhost,react@18.2.0and image names likelogo@2x.pngare not addresses.- Phone numbers — [PHONE_1]
- A
+and country code with 8–15 digits in all (the E.164 limit), e.g.+44 20 7946 0958; a North American number in(415) 555-2671or415-555-2671form, whose area code and exchange cannot start with 0 or 1; or a national number that starts with a 0 trunk prefix in space- or dash-separated groups, e.g.020 7946 0958or01 23 45 67 89. Not phones: dates (2026-09-22,22/09/2026), times, version numbers (10.0.19045) and runs of digits with no separators. Limit: a national number with no+and no leading 0, such as a Danish12 34 56 78, is indistinguishable from other numbers and is not masked. - IBANs — [IBAN_1]
- Two-letter country code, two check digits and the account part (spaces every four characters allowed), at the exact length that country uses (22 for GB and DE, 18 for DK and NL, 27 for FR…), passing the ISO 13616 mod-97 check.
GB82 WEST 1234 5698 7654 32is masked; change any one digit and the check fails, so it is not. - National ID numbers — [CPR_1] [SSN_1] …
- Twenty-one, each checked against its issuing authority's or its defining law's published structure: the Danish CPR number, Swedish personnummer and samordningsnummer, Norwegian fødselsnummer and D-number, Finnish henkilötunnus (HETU), Dutch BSN, UK National Insurance number, US Social Security number, German Steuer-ID, French NIR, Spanish DNI and NIE, Italian codice fiscale, Polish PESEL, Belgian national register number, Icelandic kennitala, Czech and Slovak birth number, Bulgarian EGN, Croatian OIB, Irish PPS number, Slovenian EMŠO, Austrian social insurance number and Swiss AHV number. Dates must be real and check digits must match. Where a random number passes too easily — the CPR number and the SSN have no check digit at all, and 1 in 11 nine-digit numbers passes the BSN 11-proef — the number is only masked when one of its names (
CPR,SSN,BSN,personnummer,NI number,Steuer-ID,DNI…) stands within 40 characters before it, soorder 123456782stays. The HETU and the codice fiscale are distinctive enough to be masked on their own. - Payment card numbers — [CARD_1]
- 13 to 19 digits, with single spaces or dashes allowed, that pass the Luhn check and start with a real issuer prefix at that issuer's length (Visa 4…, Mastercard 51–55 and 2221–2720, Amex 34/37 at 15 digits, Discover, JCB, Diners, UnionPay, Maestro).
4111 1111 1111 1111is masked;4111 1111 1111 1112fails Luhn and is not. The expiry date and CVV are not recognised on their own. - Names and street addresses — suggested, never hidden on their own — [NAME_1] [ADDRESS_1]
A capitalised given name followed by a capitalised surname (
Jens Hansen, alsoMary Ann Smith,Jens P. Hansen, andSanne de Vrieswithvan,de,von derand similar particles). The given name must be on one of the published lists below. The surname is accepted when it is on a surname list, or when it is any other capitalised word that is not a common word, weekday, month or place, soVisual Studio Code,Google Chrome,On MondayandNew York Timesare not flagged. A given name that is also an ordinary word or a place, such asWill,MayorAustin, only counts before a listed surname:Will Smithis suggested,Will thisis not.Street addresses need a street line and a postcode of the right shape after it, separated by a comma or a line break: Danish and Norwegian
Vesterbrogade 12, 1620 København V(four digits, 0800–9990 in Denmark, 0001–9991 in Norway, and a street name ending in a street word such as -vej, -gade, -gata or -veien); SwedishDrottninggatan 5, 111 51 Stockholm(NNN NN); GermanHauptstraße 5, 10115 Berlin(five digits, 01001–99998); DutchDamrak 1, 1012 LG Amsterdam(NNNN AA); British221B Baker Street, London NW1 6XE(the postcode pattern from the UK government's data standards); and US1600 Pennsylvania Avenue NW, Washington, DC 20500(number, street and suffix, city, a real state code, ZIP or ZIP+4).Tap Hide and every occurrence of that exact text, in any letter case, becomes [NAME_1] or [ADDRESS_1] and comes back when you un-mask. Also add to my words to always hide puts it on your saved list instead, so it is hidden next time too. What it misses: a first name on its own (
Jens), names writtenHANSEN, Jensor in all capitals, given names not on the lists (in a test on this build:Pieter,WolfgangandBjörnare missing), addresses without a postcode, and other countries' address shapes. What it flags wrongly: a listed first name before any capitalised word, such as a company calledEmily Studios. Measured before this section was written, over 15,000 words of this site's pages and its maker's working notes, it suggested three names, all of them real, and nothing else; on your text it may do worse.The lists, lower-cased and merged into one 230 KB file (names.json), downloaded from this site the first time you paste something and never sent anywhere: US Census Bureau 1990 first names (5,494, public domain) and 2010 surnames (the 20,000 most common of 162,253, public domain); Statistics Norway first names and surnames (2,150 first names and the 3,705 surnames used by 200 or more people, CC BY 4.0); and the Office for National Statistics baby names for England and Wales, 2025 (the 1,000 most common for boys and for girls, Open Government Licence v3.0). All fetched on 26 September 2026. Danmarks Statistik and Statistics Sweden publish name counts only through search pages with no downloadable list, and the US Social Security baby-name file refused automated downloads, so they are not used.
- IP addresses — [IPV4_1] [IPV6_1]
- IPv4: four numbers 0–255 without leading zeros, not part of a longer dotted run, so
999.1.1.1and10.0.19045.2965are not addresses;0.0.0.0,127.0.0.1and255.255.255.255identify nothing and are skipped. IPv6: eight groups of up to four hex digits, or fewer with one::, optionally ending in an IPv4 address or a%eth0zone;::1is skipped, and times such as12:30:45or MAC addresses do not parse as IPv6. - User names in file paths — [USER_1]
- Only the account folder of
C:\Users\jens.hansen\(also with forward slashes, or doubled backslashes inside JSON),/Users/jens/and/home/jens/, so a stack trace keeps its shape:C:\Users\[USER_1]\AppData\Local\…. Accounts that name no person are left alone:Public,Default,All Users,Shared,root,ubuntu,node,www-dataand CI accounts such asrunner. It misses a user name anywhere else in a path (D:\dev\jens\) or in the text. The full rule. - Internal host names — [HOST_1]
- Names under the private-network suffixes
.internal,.local,.lan,.home.arpa,.localdomain,.intranetand.corp, and hosts inside acorp.orintranet.zone such asdb01.corp.acme.com. In a URL only the host is hidden, sohttps://[HOST_1]:8443/v2/healthkeeps its port and path. A public domain is never masked by this rule; add your company's domain to your word list if it should go too. It misses internal hosts with public-looking names and may flag a Python module path such asmyapp.settings.local. The full rule. - MAC addresses — [MAC_1]
- Exactly six hex pairs with one separator throughout (
00:1A:2B:3C:4D:5E,00-1A-2B-3C-4D-5E) or Cisco's001a.2b3c.4d5e. IPv6 addresses, times such as12:34:56.789, git hashes and hex dumps are left alone; a MAC written with no separators is missed. The full rule.
Your own words — [CUSTOM_1]: anything on your list of words to always hide, matched as literal text either as a whole word or anywhere. Where one overlaps a match from the rules above, the longer of the two wins.
Never masked by any rule: UUIDs, git commit hashes, SHA-256 digests, dates, times and version numbers — unless they sit after a secret-named key such as token=, in which case the key is what gives them away.
How the placeholders come back
Each distinct value gets one placeholder, numbered by type in the order it first appears, and the same value always gets the same placeholder — so if alice@example.com appears in five log lines, the AI sees [EMAIL_1] five times and can still tell it is one person. If your text already contains something like [EMAIL_1], the numbering skips it so the two can never be confused.
DB_PASSWORD=hunter2 → DB_PASSWORD=[PASSWORD_1] alice@example.com failed login → [EMAIL_1] failed login from 203.0.113.7 → from [IPV4_1]
When you paste the answer into step 2, every placeholder the page issued is swapped back, wherever the AI put it: inside `backticks`, quotes, bold text, code blocks, next to punctuation, or with the brackets and underscore escaped as \[EMAIL\_1\]. Bracketed tokens it did not issue, like [TODO_1] or a placeholder the AI invented, are left exactly as they are.
Why mask before pasting instead of asking the AI to ignore it
Once text is sent to a chat service it has left your machine: it may be stored in the conversation history, reviewed for abuse, or used for training depending on the service and your settings. An instruction like "ignore the password" arrives together with the password. Masking has to happen before the paste, on your side — which is why this page does it in the browser and keeps the key to the placeholders in the tab.