API Keys: What They Are, Where They Go, How They Leak
Security First — Part 2 of 30
The $47,000 Mistake
In early 2025, a solo developer shipped a weekend side project — a small web app that used OpenAI to summarize news articles. The AI helped write every line of code. They deployed it, shared it in a forum, and went to bed.
By morning, someone had found the OpenAI API key embedded in the app's JavaScript. Bots had hammered the API all night. The bill: $47,000. The developer had no idea the key was visible. The AI that helped build the app hadn't warned them.
This kind of story isn't rare. In November 2025, researchers at Wiz found that 65% of the Forbes AI 50 companies — startups with a combined valuation over $400 billion — had exposed API keys and access tokens on GitHub. In February 2026, Truffle Security scanned a snapshot of popular websites and found 2,863 live Google API keys sitting in public JavaScript code, now suddenly capable of accessing Google's Gemini AI and racking up charges for their unsuspecting owners.
If you're building with AI tools, you have API keys. Let's make sure you understand exactly what they are — and how to keep them safe.
What Is an API Key?
Think of an API key as a hotel key card. The hotel (say, OpenAI or Stripe) gives you a key card when you check in. Every time you call room service — every time your app makes a request — you show that key card. The hotel charges the room, gives you the service, and moves on.
The critical difference from a password: an API key proves who to bill, not who you are. Anyone who finds your hotel key card can order room service and charge it to your account. The hotel doesn't check names. It checks key cards.
Here's what an API key typically looks like:
OpenAI: sk-proj-xK9mN2...Tz8qR
Google: AIzaSyD3...mNpQr
Stripe: sk_live_4eT...Kx9
Anthropic: sk-ant-api03-...
They're long strings — hard to guess, easy to copy.
Where API Keys Are Supposed to Live
The rule is simple: API keys live on the server, never in the client.
"Server" means code that runs on your machine or in a cloud function — code users can't read. "Client" means code that runs in the user's browser — code that is completely visible to anyone who opens Developer Tools.
Here's the correct pattern:
The wrong way (JavaScript in the browser):
// NEVER DO THIS — anyone can open DevTools and see this
const response = await fetch('https://api.openai.com/v1/chat/completions', {
headers: {
'Authorization': 'Bearer sk-proj-xK9mN2...Tz8qR' // Exposed!
}
});
The right way (environment variables on the server):
# In your Python backend — this runs on YOUR server, not in the browser
import os
import openai
# Key loaded from environment, not hardcoded
client = openai.OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello"}]
)
How you set the environment variable (terminal):
# On your local machine, in your shell config (~/.bashrc or ~/.zshrc)
export OPENAI_API_KEY="sk-proj-xK9mN2...Tz8qR"
# Or use a .env file (see below) — and NEVER commit it to Git
The .env file approach:
# .env file — stays on your machine, never goes to GitHub
OPENAI_API_KEY=sk-proj-xK9mN2...Tz8qR
STRIPE_SECRET_KEY=sk_live_4eT...Kx9
DATABASE_URL=postgresql://user:password@localhost/mydb
# Load it in Python with python-dotenv
from dotenv import load_dotenv
import os
load_dotenv() # Reads .env file into environment variables
api_key = os.environ.get("OPENAI_API_KEY")
// Or in Node.js with the dotenv package
require('dotenv').config();
const apiKey = process.env.OPENAI_API_KEY;
One critical companion file — add this to .gitignore immediately:
# .gitignore — tells Git to ignore these files forever
.env
.env.local
.env.production
*.pem
secrets.json
The Three Ways Keys Leak
1. Committed to a Git Repository
This is the most common. You build something with AI assistance, the AI puts the key directly in the code, you run git push, and it's on GitHub. Even if you delete the key in the next commit, Git never forgets — the key lives forever in your commit history.
The Wiz research from November 2025 found leaked credentials "buried deep in deleted forks, gists, and developer repos most scanners never touch." Bots scan GitHub continuously for key patterns. The window between push and exploitation is often measured in minutes.
2. Embedded in Client-Side Code
This is the scenario from the opening story, and it's exactly what the Truffle Security researchers found in February 2026 with those 2,863 Google API keys. Developers embedded keys in JavaScript to call Google Maps or other services, and when Google later enabled the Gemini API on those same projects, those same keys suddenly had the power to access AI endpoints and generate huge bills.
As Truffle Security put it: "Thousands of API keys that were deployed as benign billing tokens are now live Gemini credentials sitting on the public internet."
Browser JavaScript is public. Period. Never put a key there.
3. Left in Logs, CI/CD Pipelines, or Environment Dumps
Your app prints a debug line that includes request headers. Your CI/CD pipeline echoes environment variables during a build. You paste a .env file into a Slack message to debug something with a teammate. Keys escape all the time through channels that feel "internal" but aren't.
The 2026 Wallarm API ThreatStats report identified these as common exposure points: tokens committed to repositories, long-lived tokens without rotation, tokens exposed in logs or CI/CD pipelines. Once a key is in a log aggregation service that an attacker accesses, they have it.
What to Do Right Now
If you have a project with API keys, take 15 minutes and do this:
Immediate actions:
- Find every API key in your project with a search:
grep -r "sk-" . --include="*.js" --include="*.py" --include="*.ts" - Move any hardcoded keys into a
.envfile - Add
.envto your.gitignoreimmediately - Check if
.envis already tracked by Git:git ls-files .env— if it returns anything, it's already committed - If any key was ever committed, rotate it now at the provider's dashboard (OpenAI, Google, Stripe, etc.) — a deleted commit doesn't make it safe
For new projects:
- Create
.gitignorebefore your first commit — add.envto it before you write a single line of code - Set up environment variables on your hosting platform (Vercel, Railway, Render, Fly.io all have a "Secrets" or "Environment Variables" section)
- Use the minimum permissions possible when creating a key — if you only need read access, don't create a key with write access
- Set spending limits on your API provider accounts so a leak doesn't cost you thousands
Free tools to help:
- GitHub Secret Scanning — automatically alerts you if a known key pattern is pushed to a public repo
git-secrets— a pre-commit hook that blocks commits containing secretsdetect-secrets(by Yelp) — scans your codebase for anything that looks like a credential
# Install detect-secrets and scan your project
pip install detect-secrets
detect-secrets scan > .secrets.baseline
When Things Go Wrong
If you think a key has leaked, move fast:
- Revoke it first — go to the provider dashboard and disable the key before anything else
- Generate a new key and update your app with the new one
- Check usage logs — most providers (OpenAI, Google, Stripe) show recent API activity; look for anything unfamiliar
- Clean your Git history if it was committed:
git filter-repo --replace-text replacements.txtis the modern tool for this - Set up alerts — many providers let you set email alerts for unusual spending spikes
A Note for Vibe Coders
When you ask an AI to build something for you, it will often put keys directly in the code to make the example work. That's fine for understanding the concept — it's not fine for shipping. Before you run git push or deploy anything, do a key audit. The AI built it; you're responsible for securing it.
No API provider will refund charges that result from a leaked key. That's on you. Fifteen minutes now saves thousands of dollars later.
Ask The Guild
Community prompt: Have you ever accidentally exposed an API key — or caught yourself about to? What was the situation, and what did you do about it? Drop your story in the comments. No judgment here — this happens to everyone, and sharing the war stories is how we all get better at this.
Also: what's the first thing you're going to check in your current project after reading this?
Tom Hundley is a software architect with 25 years of experience helping developers build and ship better software. He writes the Security First series for the AI Coding Guild.
Sources: Truffle Security / BleepingComputer — Google API key Gemini exposure, Feb 2026 | Wiz — AI startup credential leaks on GitHub, Nov 2025 | Wallarm 2026 API ThreatStats Report | The Hacker News — 2,863 exposed Google API keys, Feb 2026