API keys exposed in client-side JavaScript
Anything shipped to the browser — inline scripts, bundled JS, source maps — can be read by anyone. Secret keys (OpenAI, Stripe secret, AWS, database URLs) embedded in frontend code are effectively published.
What it is
Build tools inline environment variables at compile time. If you reference a secret in client code, it ends up in the JavaScript bundle that every visitor downloads.
There's a crucial split: publishable/anon keys (Stripe pk_live, Firebase web config) are designed to be public, but secret keys (sk_live, service-role keys, provider API keys) are not and must never reach the browser.
Why it matters
A leaked provider key lets anyone run up usage on your account — LLM bills, SMS charges, cloud spend — or access data the key authorizes.
Attackers scrape JavaScript bundles at scale looking for key patterns. A committed secret is usually abused within minutes of going live.
How to fix it
Call third-party APIs from a server route or backend, never from the browser. The browser talks to your endpoint; your endpoint holds the key.
// app/api/summarize/route.ts (server-only)
export async function POST(req: Request) {
const { text } = await req.json();
const r = await fetch("https://api.openai.com/v1/responses", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.OPENAI_API_KEY}` },
body: JSON.stringify({ model: "gpt-4o-mini", input: text }),
});
return Response.json(await r.json());
}In Next.js only variables prefixed with NEXT_PUBLIC_ are exposed to the browser. Never put a secret behind that prefix — use it only for values that are safe to be public.
If a secret has shipped to the browser, revoke and reissue it. Removing it from the next build doesn't invalidate copies already scraped.
FAQ
Is my Stripe publishable key (pk_live) a problem in the frontend?
No — publishable keys are meant to be public. The risk is the secret key (sk_live), which must stay server-side.
Can I just obfuscate the key?
No. Obfuscation is trivially reversible. The only fix is to keep the secret off the client entirely.
Is your app affected?
AppSafe checks for this and dozens of other issues in one free scan.
Scan my app freeFrom the blog
Fake AI crawlers are hunting your .env files. Here's how to check yours
Credential scanners are borrowing the names of AI crawlers to slip past allowlists, and they're asking for one file in particular: your .env. How to check whether yours is reachable, and how to lock it down.
The Railway breach: how to rotate your app's secrets without downtime
Railway told every user to roll their environment variables after attackers went after AI and platform API keys. How to check your exposure, rotate everything without taking your app down, and make the next breach hurt less.
Shipping an AI-built app? Check these 7 things before you launch
AI coding tools optimize for "it works," not "it's safe to ship." These are the seven issues we check for first on any freshly launched app — and the fix for each one.
Related guides
Exposed .env files: how attackers find your secrets
A single reachable .env can hand over your whole stack.
Supabase Row Level Security (RLS): lock down your tables
Your anon key is public. RLS is the only thing between it and your data.
Firebase Security Rules: stop leaving your database open
Your Firebase config is public by design. Your rules decide who sees the data.
Source maps in production leak your source code
Shipped .map files hand over your original source.