How BrassCoders Catches Hardcoded Secrets in AI Code

AI assistants hardcode realistic-looking API keys into example code. BrassCoders bundles detect-secrets and adds custom formats, covering 20+ credential types.

Copper Sun Brass Team · · 4 min read
securityoss-core

AI assistants hardcode credentials. They generate example code with a realistic-looking API key, a developer copies the example, and the key literal ships with it. GitGuardian counted 12.8 million secrets exposed in public GitHub commits in a single year, and AI-generated code adds a fresh source of them. BrassCoders bundles a proven secret scanner, extends it to the keys the AI era introduced, and redacts every match before it’s written anywhere.

Why AI-Generated Code Leaks Credentials

BrassCoders treats hardcoded secrets as the highest-frequency AI-coder bug class. They’re rarely dramatic and almost always present. Two mechanisms drive it. AI assistants generate config stubs and demo code with credentials baked in, because that’s how the tutorials in their training data were written. They also reproduce secret-shaped strings verbatim.

The second mechanism is the unsettling one. Carlini et al. (ICLR 2023) showed that language models memorize and reproduce verbatim sequences from training data, including API keys from leaked repositories, at a rate that climbs with model size. A secret-shaped string in AI-generated code is not safely assumed to be a placeholder. The broader evidence base is in the secret-leakage research.

What BrassCoders Detects

BrassCoders combines Yelp’s detect-secrets with a custom format layer to cover more than 20 credential types. detect-secrets brings the entropy scoring and regex; the custom layer adds the AI-era keys it doesn’t ship rules for.

detect-secrets scores strings two ways: regex matches for known credential formats, and Shannon entropy for high-randomness strings that look like secrets even without a known shape. It covers AWS access keys, GitHub PATs, Slack tokens, RSA private keys, Stripe keys, and roughly 40 formats total.

The custom secret-pattern layer extends that to OpenAI keys (sk-...), Anthropic keys (sk-ant-...), SendGrid, Mailgun, Twilio, DigitalOcean, and NPM publish tokens — the providers an AI assistant writes into example code today that a 2020-era scanner has no rule for. The combined coverage is the 20+ formats. The field guide to what shows up in practice is Secrets Your AI Might Leak.

Redacted at the Scanner, Never Transmitted

BrassCoders redacts the credential value at the scanner, before it reaches any output file. A finding records where the secret is and what format it matched; it never records the secret itself. So the report you hand to your AI assistant shows AWS access key at config.py:14, not the key.

This matters because the output is meant to travel. You paste .brass/ai_instructions.yaml into Claude Code or Cursor, and a redacted finding is safe to share where the raw credential would not be. The OSS core also makes zero outbound network calls, so the scan itself never sends a flagged secret anywhere. The redaction holds at two points: the scanner that finds the value, and the serialization boundary that writes the file.

Treat Every Flag as Compromised

BrassCoders reports the match; the rotation decision is yours, and the safe default is to assume the worst. A credential that reached a scanner has, by definition, been committed to a file, and Carlini’s result means it might be a real key the model reproduced rather than a fixture. Rotate it.

This is the division of labor in miniature. BrassCoders deterministically reports every secret-shaped string it can match, with no guess about whether a given one is live or a test dummy. Your AI assistant can help sort the obvious fixtures from the live keys, but the scanner’s job is recall: surface them all, redacted, and let the judgment happen with full information.

Run It

The secret scan runs in every scan, no flag required. Install BrassCoders and run it:

pipx install brasscoders
brasscoders --offline scan

Secret findings land in .brass/security_report.yaml, each tagged with the scanner that flagged it, so you know whether detect-secrets or a custom pattern caught a given credential. For the full set of detectors in the same pass, see what BrassCoders detects.

Frequently Asked Questions

How do AI assistants leak secrets into code?

Two ways. They generate example code with realistic-looking API keys, and developers paste the example with the key literal still in it. They also reproduce credential-shaped strings memorized from training data — Carlini et al. (ICLR 2023) showed language models reproduce verbatim sequences, including API keys, from leaked repositories. BrassCoders flags hardcoded credentials at scan time.

What credential formats does BrassCoders detect?

More than 20. It bundles Yelp's detect-secrets (entropy scoring plus regex for AWS keys, GitHub PATs, Slack tokens, RSA private keys, and Stripe keys, ~40 formats) and adds a custom layer for the formats detect-secrets doesn't ship rules for: OpenAI (sk-), Anthropic (sk-ant-), SendGrid, Mailgun, Twilio, DigitalOcean, and NPM publish tokens.

Does BrassCoders store or transmit the secret it finds?

No. The credential value is redacted at the scanner before anything is written to output — the finding records the location and the format, not the secret itself. The OSS core makes zero outbound network calls, so nothing about a flagged secret leaves your machine.

What should I do with a flagged credential?

Treat it as compromised and rotate it, even if it looks like a placeholder. Carlini's research means an AI-generated secret-shaped string could be a real credential reproduced from training data, not a dummy. Rotating a key is cheap; assuming a live key was fake is the expensive mistake.

How do I run the secret scan?

It runs in every brasscoders scan, with no flag to set. Install with pipx install brasscoders and run brasscoders --offline scan; secret findings land in .brass/security_report.yaml, each tagged with the scanner that flagged it.