Exposed API Keys in Frontend Code — A Security Mistake That Can Cost You Everything
Accidentally exposed an API key in your frontend JavaScript? Here's why it happens, what attackers can do with it, and the correct way to handle secrets in React and Next.js apps.
Exposed API Keys in Frontend Code — A Security Mistake That Can Cost You Everything
The 3 AM Nightmare
It happens more often than developers like to admit. You are in the zone, building a feature fast. You hardcode an OpenAI or AWS API key just to "test if it works," and you push the code to GitHub. You plan to remove it later, but you forget.
Three hours later, you wake up to an email: a $4,000 billing alert. A bot scraped your public repository, found your key, spun up hundreds of EC2 instances, and started mining crypto.
This isn't a theoretical risk or a horror story to scare juniors. It happens every single week.
The Illusion of Frontend Security
Modern frameworks like React, Vue, and Next.js are incredibly powerful, but they often give developers a false sense of security. Here is the fundamental rule every software engineer must understand:
Everything in your frontend JavaScript is public. There are absolutely no secrets in client-side code.
Even if your GitHub repository is private, your application is not. Anyone can open Chrome DevTools, navigate to the Network tab, or inspect your bundled .js files, and extract your variables in plain text.
// ❌ WRONG: This is visible to ANYONE who opens DevTools
const fetchAIResponse = async (prompt) => {
const response = await fetch('https://api.openai.com/v1/chat/completions', {
headers: {
'Authorization': 'Bearer sk-proj-abc123yourrealkeyhere' // Fully Exposed!
}
});
};
Even environment variables can be dangerous if misunderstood. Variables prefixed with NEXT_PUBLIC_, VITE_, or REACT_APP_ are embedded directly into the public build. If you put a secret key in NEXT_PUBLIC_STRIPE_SECRET_KEY, you have just published it to the world.
The Correct Architecture: The Backend Proxy Pattern
The fix is universal: your frontend should never communicate with a third-party service using a secret key directly.
Instead, you must use a Backend Proxy Pattern. Your frontend makes a request to your own backend API, and your backend—safely hiding your environment variables—makes the request to the third-party service.
The Secure Workflow:
❌ Unsafe: Frontend → [Secret Key Exposed] → Third-party API
✅ Secure: Frontend → Your Backend API → [Secret Key Safely on Server] → Third-party API
Here is how it should look in practice:
// ✅ CORRECT: Frontend only calls your own API
const askAI = async (prompt) => {
const res = await fetch('/api/generate-response', {
method: 'POST',
body: JSON.stringify({ prompt })
});
return res.json();
};
// ✅ CORRECT: Backend (e.g., Node.js / Next.js API Route) handles the secret
export async function POST(req, res) {
const { prompt } = await req.json();
// The secret key never leaves the server
const response = await fetch('https://api.openai.com/v1/chat/completions', {
headers: {
'Authorization': Bearer ${process.env.OPENAI_SECRET_KEY}
},
body: JSON.stringify({ prompt })
});
const data = await response.json();
return res.status(200).json(data);
}
Damage Control: What to Do If You Already Leaked a Key
If you realize a key has been pushed or exposed, do not panic, but act immediately.
Revoke the key immediately: Go to the provider's dashboard (AWS, Stripe, OpenAI), delete the compromised key, and generate a new one. Do this before you fix the code.
Audit your logs: Check your usage dashboards to see if the key was abused. Look for unauthorized transactions, strange database queries, or spiked API usage.
Clean Your Git History: Simply deleting the key in your next commit is not enough; the key will still exist in your Git history. Use tools like
git filter-repoor BFG Repo-Cleaner to purge it completely.
The Ultimate Security Checklist
Before launching any project, run through this checklist to ensure your API keys are locked down:
.gitignore is configured: Verify
.env,.env.local, and other secret files are ignored before your first commit.No secrets in frontend directories: Double-check your
src/,components/, andpages/folders.Prefixes are used correctly: Ensure
NEXT_PUBLIC_orVITE_variables only contain truly public data (like API base URLs or public Stripe keys).Backend routing is implemented: All third-party calls requiring a secret key are routed through your server.
Secret scanning is enabled: Turn on GitHub Secret Scanning for automated alerts on accidental commits.
The Golden Rule: If it grants access to data or money, it lives on the server. No exceptions.
Published by Logic Node Studio — Backend Security Series
You Might Also Like
Custom Software vs a Generic Website
A lot of business owners come to us asking for a website. After a short conversa...
The Silent Killer of Conversions: Why Slow Initial Page Loads Are Ruining Your SaaS Business
Imagine this: You’ve spent months perfecting your SaaS product. Your landing pag...
Top 50 UI Component Libraries for Web Developers in 2026 (With Links)
Building modern, responsive, and visually stunning websites no longer requires w...
0 Comments
Sign in to join the conversation
Sign In to CommentNo comments yet. Be the first to share your thoughts!