NewEvery finding now mapped to CWE, OWASP Top 10 & CVSS
all posts
Engineering2 min read

Your Anthropic key was being verified against OpenAI

A four-character oversight in a regex meant every Anthropic key was reported twice and checked against the wrong company’s API. Here’s how it surfaced.

We shipped live-key verification and, before trusting it, ran it against a synthetic bundle containing one of everything: an OpenAI key, an Anthropic key, a Stripe key, a Slack token, a GitHub token, an AWS access key ID.

The output had two things wrong with it.

hits: [
  'OpenAI API key',
  'OpenAI API key',     ← two?
  'Anthropic API key',
  ...
]

[CRITICAL] Anthropic API key exposed, confirmed live
  verification=live :: Key authenticated against the OpenAI API.
                                                  ↑ wrong company

Bug one: the pattern was too generous

OpenAI keys start with sk-. Anthropic keys start with sk-ant-. Our OpenAI pattern was /\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\b/, which happily matches sk-ant-… as well, because sk-ant-ABC is a perfectly good sk- string.

So every Anthropic key was detected twice: once correctly, once as an OpenAI key. Duplicate findings in a report are worse than they sound, they inflate the critical count and make the tool look like it can’t tell vendors apart, which it couldn’t.

// before
/\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\b/g

// after — exclude the Anthropic prefix explicitly
/\bsk-(?!ant-)(?:proj-)?[A-Za-z0-9_-]{20,}\b/g

Bug two: the results bled together

The second problem was worse, and the first one is what exposed it. Verification results were cached in a map keyed by the raw credential value, so the same key found in five bundles would only be probed once. Sensible optimisation.

But one value was now matching two credential kinds. The OpenAI dispatch ran first, wrote its verdict under that value, and the Anthropic entry read the cached result, inheriting a verdict produced by asking entirely the wrong company. api.anthropic.com was never contacted at all.

The fix is to key by kind and value together. Same value, two credential shapes, two independent probes.

Why a fixture caught it and a real scan wouldn’t have

This is the part worth keeping. Both bugs are invisible unless your test input contains two credential formats that overlap. Scan a real app and you’ll typically find one vendor’s key, get a plausible-looking verdict, and ship.

The test that finds this class of bug isn’t “does it detect a key.” It’s “does it detect the right key when two formats overlap, and does it ask the right company.”

The same overlap existed in our repository scanner, which had been carrying it for as long as both patterns had been in the file. One fix, two places.

Written by the Flare.ai team.

Curious what your app is leaking?

One free scan per site. No account, under a minute.

Run your free scan