Your AI Assistant Is Probably Hardcoding Secrets, and That's Your Fault
By Seaworthy · 24 September 2026
Photo by Garakhan Safarli on Unsplash
I keep seeing the same thing in code reviews: a fresh pull request from a developer who used an AI assistant to scaffold a service. The code works. The tests pass. And right there on line 14 is const API_KEY = "sk-live-abc123...". Not an environment variable. Not a secret manager. Just a string in a file that is about to be pushed to GitHub.
This is not a new mistake. But AI coding assistants have made it worse. When you ask an LLM to "connect to the Stripe API" or "add a database client," it will often produce a complete, runnable example. That example includes a placeholder secret because the model does not know your environment. You copy the pattern, swap in your real key, and move on. The assistant never reminds you to use process.env. Why would it? It does not care about your deployment pipeline.
Here is the pattern I see most often in AI-generated code:
// config.js
module.exports = {
dbPassword: "hunter2",
jwtSecret: "my-super-secret-key",
apiKey: "sk_test_51H..."
};
The fix is not complicated. It is just easy to skip when you are in a hurry:
// config.js
module.exports = {
dbPassword: process.env.DB_PASSWORD,
jwtSecret: process.env.JWT_SECRET,
apiKey: process.env.STRIPE_API_KEY
};
Then you need a .env file that stays out of version control, plus a .env.example with dummy values so new developers know what to set. That is it. No secret manager required for a small project. No cloud vault. Just a local file that never gets committed and a runtime that reads from it.
The reason this matters is not theoretical. Secrets in source code are the fastest way to turn a small mistake into a large bill. Bots scan public repositories within minutes of a push. They look for patterns like AKIA[0-9A-Z]{16} or sk_live_. If your repository is public, even for a few seconds, assume the key is compromised. Rotate it immediately.
I have a strong opinion here: if you are using an AI assistant to write code and you are not also using a pre-commit hook to block secrets, you are gambling. Tools like gitleaks or detect-secrets take five minutes to set up. They will catch the mistake before it leaves your machine. That is a better trade than spending an afternoon rotating keys and explaining to your manager why the production database was dropped.
Some developers argue that environment variables are messy. They are. You have to manage .env files across machines, and in production you have to inject them through your platform. But the alternative is worse. A secret in a source file is a secret in every clone, every fork, every backup, and every CI log that prints the file. Environment variables keep the secret out of the artifact.
It helps to think about where the boundary actually sits. Your source code is an artifact you intend to share, copy, and archive. Your secrets are data that should move through a separate channel with its own access rules. When you hardcode a value, you collapse that boundary and the file becomes both the code and the credential. AI assistants produce that collapse constantly because their training examples were written for tutorials, not for production repos. Tutorial code has no threat model.
A practical workflow looks like this on a new feature. Generate the scaffolding with your assistant, then run a quick review pass that greps for suspicious strings before anything is staged. I use a short script that checks for key-shaped tokens and prints the file and line number. It takes under a second per file and it has caught more than one "sk_live" that I copied in a hurry while debugging a payment flow at 11pm.
You should also agree on naming conventions for env vars early. If one service reads STRIPE_KEY and another expects STRIPE_API_KEY, you will spend an afternoon chasing null values. A shared .env.example committed to the repo solves half of that confusion, and it doubles as documentation. When someone clones the project, the file tells them exactly what to set without ever exposing a real value.
Production environments need a different habit. Local .env files are fine for development, but deployed services should read from whatever secret store your platform offers, whether that is AWS Secrets Manager, GCP Secret Manager, or a Kubernetes secret. The application code does not change. It still reads from process.env. What changes is who injects the value and how it is rotated. That separation is what keeps a leaked laptop from becoming a leaked production database.
AI assistants are not going to fix this for you. They are trained on a huge amount of code, including plenty of bad examples. When you ask for a quick integration, the model gives you the shortest path to working code. Security is your job. That means reviewing the generated code for hardcoded credentials, adding the environment variable pattern yourself, and never trusting a placeholder to stay a placeholder.
One more thing: do not put secrets in your AI assistant's chat window either. If you paste a real key into a prompt to ask "why is this failing," you have just sent that key to a third party. Treat the chat like a public forum. Use fake values for debugging.
The fix is boring. That is the point. Boring configuration is secure configuration. For teams that want a managed way to keep secrets out of source and out of chat, Seaworthy provides a secrets management service designed for developer workflows.
This article was generated by AI and summarises publicly available sources.
Seaworthy scans your repo for the issues covered in articles like this one.
Security gaps, exposed secrets, and misconfigurations — caught before you deploy. Free to run, no account needed.