Dev.to Security 🔐 Cybersecurity 👁 0 📖 3 min read

How to keep API keys out of AI-generated code

Practical checklist from ShipSafeStack. Not a penetration test, compliance audit, score, or proof that an app is safe to launch. Informational only — no guarantees. The frontend checklist is how to search the bundle aft

Practical checklist from ShipSafeStack. Not a penetration test, compliance audit, score, or proof that an app is safe to launch. Informational only — no guarantees.

The frontend checklist is how to search the bundle after the app is built. This page is how to keep the secret out of the code an agent writes. They overlap — do both.

Hand the agent a name, not a value

Agents inline a key because the request fails without it. Put the value in the host’s secret store, or in a local file that git and the agent ignore, and tell the agent the variable name.

Vendor docs (as of the guide on ShipSafeStack):

  • Cursor: .env is ignored by default; .cursorignore can block extra paths. A terminal command or MCP tool can still read an ignored file.
  • Lovable: VITE_ values belong in .env because they are public build-time values; Stripe / Resend / model keys belong in Secrets for Edge Functions.
  • Bolt: server functions read the secret; the value should not be plain text in the code.

Do not paste a live key into the chat to “make it work.” The transcript is another copy. A GitHub token pasted there is the same class of leak as Leaked a GitHub token?.

Sort the key before the agent touches it

Key Vendor’s instruction Where it may live
Stripe pk_ Publishable; cannot create charges or read account data Client
Stripe sk_ / rk_ Not safe to expose; prefer a restricted key with only the permissions that job needs Server environment
Stripe whsec_ Webhook signing secret; verify the raw body with it Server environment
Supabase publishable / legacy anon Safe in the browser only with RLS and least-privilege grants Client
Supabase secret / service_role Bypasses RLS; never in the client Server environment
Firebase API key (restricted to Firebase APIs) Public by design; Security Rules authorize data Client config
Model, email, or DB URL with a password Treat as secret unless that vendor’s docs call it publishable Server environment

Stripe’s docs also say not to put sensitive keys in source or committed files, and not to share them in chat or email.

Stop the file from being written

  • Tell the agent which env var names to read and that secrets are already configured on the host.
  • Keep secret files out of git (.gitignore) and out of agent context where the tool supports it.
  • Prefer server routes / Edge Functions for privileged calls; the browser should call your backend, not hold the secret.
  • Do not “hide” a key by encoding it, splitting the string, or fetching it from a public JSON file — that is the same leak with extra steps.

If the secret is already in the code

  1. Rotate it at the vendor before or as you redeploy. Assume the old value was copied.
  2. Remove it from the client, from committed .env files, and from git history if it was pushed. Rotation without removal leaks the replacement.
  3. Check the vendor’s usage or logs for calls you did not make.
  4. Re-scan the built JavaScript on the deployed URL, not only the latest source.

Related: API keys leaking into the frontend, Supabase service role key exposed, Pre-launch security checklist.

FAQ (condensed)

  • Can I give Cursor my Stripe secret key so it can test payments? Prefer a restricted key with minimal permissions, in a server env the agent does not print back; do not paste unrestricted live secrets into chat.
  • Is the Supabase anon key safe in generated client code? Only with RLS and tight grants — details in Is the Supabase anon key safe to expose?.
  • What if the agent encoded the key? Still a leak if the browser can reverse it.
  • Does ignoring .env fix a key that was already committed? No — rotate, remove from history/deploy artifacts, then prevent the next write.

Check a public URL (passive, free): shipsafestack.com/scan — looks for secret-shaped strings in public scripts (masked), among other passive checks. Nothing stored. Informational only, not an audit.

Original: How to keep API keys out of AI-generated code

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.