AppSec Basics

Why Hardcoded API Keys Keep Ending Up in Production

It's the single most common finding in almost every codebase we scan. Not because developers don't know better, but because the environment-variable version is one extra step slower during a demo.

F Fora AI Team July 6, 2026 6 min read

Ask any developer whether hardcoding an API key into source is a bad idea, and they'll say yes without hesitation. Then look at almost any real codebase — especially anything built quickly, for a hackathon, a prototype, or "just to get it working" — and you'll find one anyway. This isn't a knowledge problem. It's a friction problem.

The moment it happens

It rarely starts as a decision. It starts as debugging. You're testing a third-party API integration, the environment variable isn't loading for some reason, so you paste the key directly into the function just to confirm the request works. It works. You move on to the next thing. The key stays.

Later, someone runs git add . without checking the diff carefully, and the key is now in the commit history — which, importantly, doesn't go away even if you delete the line in a later commit. Anyone with clone access to that repository, at any point in the future, can find it by searching the history.

Why "it's a private repo" doesn't fully solve this

A private repository narrows who can see the key, but it doesn't eliminate the risk categories that matter most:

The fix, and why it's worth the extra 30 seconds

Environment variables solve this cleanly:

import os
API_KEY = os.environ["STRIPE_SECRET_KEY"]

The key lives in a .env file (excluded from version control via .gitignore) locally, and in your hosting platform's environment variable settings in production. It's not committed, it's not in your logs by default, and rotating it is a config change rather than a code deploy.

The friction that causes people to skip this step is almost always a missing habit, not a missing tool — keep a .env.example file in the repo with every variable name and no real values, so the "correct" path is exactly as fast as the shortcut.

If a key has already been exposed

Rotate it. Don't just remove the line from the current file — the old value is still valid until you generate a new one and revoke the old one at the provider. Removing it from the code without rotating the key protects you from nothing.

← Back to all posts