Claude Code hardcoded a Stripe key. Here's how it happens.
Short answer: AI coding agents hardcode secrets because a literal value is the shortest path to a passing test, and linters stay silent because a hardcoded string is valid syntax. The fix is a local security gate — shipguard scan --strict — that knows sk_live_ is a Stripe secret and exits non-zero before you deploy.
Ask an agent to “make checkout work” and it will — and if your key is in the prompt context, it pastes it straight into the source. The test passes. The diff looks clean. You ship.
The exact pattern
It almost always looks like this — a working value used directly instead of an environment lookup:
Why linters don't catch it
Linters check style and syntax, not consequence. A hardcoded string is valid JavaScript. What’s needed is a check that knows sk_live_ is a Stripe secret and refuses with a non-zero exit code.
We ran it through the gate
Here’s the actual output from scanning the repo above — a real Next.js checkout the agent wrote, before any human review:
fig.1 — one command, ~0.6s, two criticals caught before deploy.
secrets check matches dozens of API-key and token formats — locally, in about 2 seconds, without your code leaving the machine.Gate it before the deploy
Add shipguard scan --strict to your pre-push hook or deploy script. Exit codes do the rest: exit 0 ships, exit 1 blocks. Agents understand exit codes natively — which means the same gate that protects you from your agent also works for your agent.
FAQ
Why do AI coding agents hardcode secrets?
Why don't linters catch hardcoded API keys?
How do I stop this before deploy?
────────[ ▮ gate ]────────
Don't ship the next one.
Free, local, no account. Catches this exact bug class before deploy.
$ npx @agenticcli/shipguard scan