A fallback secret is a pattern like this:
const secret = process.env.JWT_SECRET || 'dev-secret';
In local development, this is convenient — you don’t need a .env file set up perfectly to get the app running. The problem is that this exact same line ships to production, and if the real environment variable is ever missing — a misconfigured deploy, a renamed variable, a typo in your hosting provider’s dashboard — the app silently falls back to 'dev-secret' instead of failing loudly.
Why this is critical, not minor
If that fallback string is ever committed to a public or even semi-public repository, it’s no longer a secret — it’s a publicly known value. Every JWT signed with it can be forged by anyone who read the source code. Every webhook validated against it can be spoofed. The “fallback” isn’t a safety net; it’s a skeleton key.
Wondering if your code has any of this? Scan a public repo free, no account needed.
Scan a repo →Why AI tools generate this pattern so often
Models trained on public code have seen this exact defensive pattern thousands of times, because it’s genuinely common in tutorials and starter templates where security isn’t the point being taught. When an AI tool scaffolds your auth or webhook config, it reaches for the pattern it has seen most often — not the one that’s safest in production.
The fix
const secret = process.env.JWT_SECRET;
if (!secret) {
throw new Error('JWT_SECRET is not set');
}Fail loudly at startup if a required secret is missing. A crashed deploy is immediately visible and easy to fix. A silently-running deploy with a public fallback secret can sit unnoticed in production for months.