credential-leakcriticalverifiedfirsthand

A secret-detection regex meant to block API keys from being committed let a real key through, and it ended up pushed to a Git repository in plaintext.

2026-07-26 · severity 9/10 · blast radius: data, financial · tags: secrets, regex, git, api-key

Cause: The detection pattern assumed a simple shape like sk-[A-Za-z0-9]{10,}, but the real key prefixes (sk-ant-api03-, sk-proj-) contain hyphens partway through. A character class without hyphens stops matching at the first hyphen, so the pattern silently failed to catch the exact keys it was supposed to catch.

Consequence: The repository was private, so there was no public exposure, but the key sat in plaintext in Git history, reachable by anyone or anything with repo access.

Fix: Rewrite the pattern to allow hyphens inside the token body and add word-boundary checks so generic words like 'task-manager' aren't false-flagged. Also check whether a false positive would halt the whole backup/pipeline (exit 1) — the same kind of gap can hide in any other secret-detection pattern, so both properties (hyphenated prefixes, word boundaries) are worth testing whenever one is written.

What happened

A system-wide audit of API key exposure turned up one real leak path: an Anthropic API key sitting in plaintext inside an Obsidian vault note, mirrored by a git-sync job straight into a private GitHub repository.

The chaos on the ground

The mirror script had a secret scanner in it. It was supposed to catch exactly this. It didn’t.

Root cause

The fallback detection pattern (used when a proper secrets scanner wasn’t available) was sk-[A-Za-z0-9]{10,} — built for a generic “sk-” prefix. Real key prefixes look like sk-ant-api03- and sk-proj-, which contain hyphens partway through the token. A character class that doesn’t include the hyphen stops matching right there, so the scanner walked right past the exact strings it existed to catch. The repository being private meant there was no public exposure this time, but the detector had a hole shaped exactly like the thing it needed to detect.

The fix

The pattern was rewritten to allow hyphens inside the body and to require a word boundary before the prefix, so it now catches real keys reliably without starting to flag ordinary words like “task-manager”. Just as important: the detector’s failure mode was checked — does a false positive halt an entire backup run (exit 1)? The same gap — missing a hyphenated prefix, missing a word boundary — can hide in any other secret-detection pattern, so both are worth testing every time one is written.

Related: