We tested 26 API key formats. Ours catches 21.
PromptScrub carries 28 detection patterns in total. Seventeen of them do nothing but recognise API keys, which sounds excessive until you try to write one pattern that covers every vendor.
We ran 26 real key formats through the rule set. Twenty-one were caught. Here is the whole table, including the five that were not.
What the rules catch
| Vendor | Shape | Result |
|---|---|---|
| OpenAI (legacy) | sk- + 20 or more | caught |
| OpenAI (project) | sk-proj- | caught |
| Anthropic | sk-ant- | caught |
| GitHub PAT | ghp_ + 36 | caught |
| GitHub fine-grained | github_pat_ | caught |
| AWS access key | AKIA + 16 | caught |
| AWS temporary | ASIA + 16 | caught |
| Slack | xoxb- and friends | caught |
| Google API | AIza + 35 | caught |
| Google OAuth | ya29. | caught |
| GitLab PAT | glpat- | caught |
| npm | npm_ + 36 | caught |
| Stripe live/test | sk_live_, rk_live_ | caught |
| Stripe webhook | whsec_ | caught |
| SendGrid | SG. + two segments | caught |
| Hugging Face | hf_ + 30 | caught |
| Shopify | shpat_ + 32 hex | caught |
| DigitalOcean | dop_v1_ + 64 hex | caught |
| PyPI | pypi-AgEIcHlwaS5vcmc | caught |
| Bearer token | Authorization: Bearer … | caught |
The pattern behind all of these is the same: the vendor put a fixed prefix on the key. A prefix is a gift to anyone writing a detector, because it turns "is this a secret" into "does this start with ghp_", and the second question has a definite answer.
What slips through
Five formats in our test were not caught, and each fails for a reason worth understanding:
| Vendor | Example shape | Why it is missed |
|---|---|---|
| Azure OpenAI | 1234567890abcdef… | 32 hex characters, no prefix at all |
| Twilio account SID | ACabcdef… | AC is too short to be distinctive |
| Mailgun | key-abcdef… | key- appears constantly in ordinary text |
| Cloudflare | v1.0-abcdef… | looks exactly like a version string |
| Supabase | sbp_abcdef… | simply not written yet |
Only the last one is a straightforward omission, and it is the kind we fix on request.
The first four are the interesting cases, because adding them would cost more than it gains. Azure's key is a bare 32-character hex string. So is an MD5 hash, a git commit hash pair, a UUID with the dashes stripped, and a session identifier in a log file. A rule matching that shape would fire on all of them. Mailgun's key- prefix is worse: it would match key-value, key-press, and every hyphenated compound starting with the word "key".
The line we draw
A detector that flags a third of your log file teaches you to ignore it. We would rather miss Azure's key than have every commit hash in a stack trace come back redacted, because a person who stops reading the warnings will miss the real one too.
That is a judgement call, not a law of nature, and it is worth stating plainly so you can decide whether you agree. If you work with Azure OpenAI daily, our default is wrong for you, and the honest answer is that the tool cannot help with that particular key.
What to do about the gap
Two practical habits cover most of it.
First, know your own stack's key shapes. If you use a vendor whose keys have no prefix, the tool will not catch them, and no pattern-based tool will. That is a fact about the key format, not about the tool.
Second, use the password rule as a backstop. Keys in configuration usually arrive as an assignment: AZURE_OPENAI_KEY=1234…. The password rule matches on the key name rather than the value, so it catches the assignment even when the value is shapeless. That rule is on by default, and it is why the two rules exist side by side rather than one replacing the other.
Third, if a format we should support is missing, tell us. The rule set is a hard-coded file in this page's source, versioned in git, and adding a prefix-based vendor is a two-line change.