Quick Answer
Here's the short version. Your AI coding agent — Claude Code, Cursor, whichever — drops a hardcoded API key straight into your codebase, or worse, bakes it into the client-side bundle that ships to every browser. Attackers scan GitHub for exposed keys around the clock. They find yours. They run up your bill until you get an abuse notice and a very bad afternoon. api-doctor catches keys in the wrong places before you ever commit them.
The problem: keys are easier to commit than to hide
Your Resend API key is a secret. It should never sit in your repo. It should never ship in your client bundle. It belongs in environment variables on your server, and nowhere else.
So what does your AI agent actually do? It hardcodes the key right into the source. Sometimes it goes a step further and drops it into a client component that gets bundled and sent to browsers.
// frontend/app.js
const RESEND_API_KEY = 'sk_resend_abc123def456xyz';
// This gets bundled and sent to every browser.
// Attackers download your JS, extract the key, use it.
I get why this happens. The model has seen thousands of examples where keys come from environment variables, but it has also seen plenty where someone hardcoded a key "just to get it working." Training data is messy like that. You run it locally, it works, you ship it, and the mistake rides along quietly.
A real example: a Resend key in the client bundle
Picture a contact form your agent just generated, API key sitting proudly at the top of the file. That key ships in your frontend bundle. Someone opens DevTools, pokes at your JavaScript, spots the key, and fires off 10,000 emails on your account. Same day, you get a $500 bill and an abuse notice. Not a great trade.
How api-doctor catches this
✗ Resend: 1 critical issue
resend-api-key-hardcoded
src/ContactForm.tsx:1
API key hardcoded in source. Move to environment variables.
Severity: critical
Security: CWE-798 (Use of Hard-coded Credentials)
It flags this before the code ever reaches GitHub, which is the whole point. You want to catch it while it's still cheap to fix. Hardcoded secrets are also just one of the agent blind spots it covers — the same pattern-copying produces the Claude Code auth bug that locks users out, and payment retries that run without an idempotency key.
How to fix it: use environment variables
Server-side client (the right way):
// lib/resend.ts (server only)
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
export { resend };
# .env.local (never commit this file)
RESEND_API_KEY=sk_resend_abc123def456xyz
API route (server-side endpoint):
// app/api/send-email/route.ts
import { resend } from '@/lib/resend';
export async function POST(req) {
const { email, subject, html } = await req.json();
const response = await resend.emails.send({
from: 'noreply@example.com',
to: email,
subject,
html,
});
return Response.json(response);
}
Client-side form (it calls your API route, not Resend directly):
// app/components/ContactForm.tsx
export default function ContactForm() {
const handleSubmit = async (e) => {
e.preventDefault();
await fetch('/api/send-email', {
method: 'POST',
body: JSON.stringify({
email: e.target.email.value,
subject: 'Welcome',
html: '<p>Welcome to our app</p>',
}),
});
};
}
Now your key never touches the client bundle, never lands in your GitHub repo, and only lives where it should: on your server.
Frequently asked questions
Q: Is it okay to hardcode keys in development? Honestly, no. Reach for environment variables from the very first line. It's a good habit, and it saves you from the "oops, I committed that" moment later.
Q: What if I accidentally commit a key? Rotate it right away in your provider's dashboard. Then walk back through your git history so you know exactly how long it was sitting out in the open.
Q: Can I keep a .env file in my repo?
No. .env files belong in .gitignore and should never be committed. For production, use a real secrets manager.
Q: How does api-doctor detect hardcoded keys?
It scans your source for the telltale patterns like sk_, sk-, and api_key =.