Third-party API key in the JavaScript bundle
What it looks like
// components/ContactForm.tsx
const res = await fetch('https://api.resend.com/emails', {
method: 'POST',
headers: { Authorization: 'Bearer re_live_...' },
body: JSON.stringify({ to, subject, html }),
})What happens
Anyone who views the page source can take the key and run up charges, send messages or pull data on your account until the key is revoked.
Where it shows up
Descriptive, not a verdict: builders and stacks whose defaults make this reachable, or that a public incident names. Each hub states the tool's own security features.
Seen in public
Escape analysed more than 5,600 publicly deployed apps built with AI app builders and found more than 2,000 vulnerabilities, over 400 exposed secrets and 175 instances of exposed personal data.
- more than 5,600 Apps analysed
- more than 2,000 Vulnerabilities found
- 400+ Exposed secrets
- 175 Exposed PII instances
Oct 2025 · Escape · all sources
Two days after announcing a SaaS built with Cursor and no hand-written code, its founder reported subscription bypasses, maxed-out API keys and unwanted database writes; he shut the app down three days later.
- 2025-03-15 Launch announcement
- 2025-03-17 Report of subscription bypass and API key abuse
- 2025-03-20 Shutdown announcement
Mar 2025 · Leo (Enrichlead founder) · all sources
Moltbook, a social network for AI agents built with AI-generated code, ran a Supabase database without row-level security policies, leaving 1.5 million API tokens and 35,000 email addresses readable and writable without login.
- 1.5 million API authentication tokens exposed
- 35,000 Email addresses exposed
- about 17,000 Human account owners in database
- 2026-01-31 Reported to maintainer
- 2026-01-31 (within about 2 hours) First fix applied
Feb 2026 · Wiz Research · all sources
Check it yourself
Uses your builder's dashboard and your browser. No tools to install.
- Open your live app in Chrome, right-click, choose Inspect, then open the Sources tab.
- Press Ctrl+Shift+F (Cmd+Option+F on a Mac) to search all loaded files. Search for
Bearer,api_key,apiKey,sk_live,sk-,AKIAandsecret. - Open the Network tab, reload, and click any request that goes to a domain other than your own or your database. Check its Request Headers for an Authorization or x-api-key value.
- A bad result is a search hit that looks like a long random string, or a request header carrying a key for a service you pay for.
What we check
We pull every script the app loads, run pattern and entropy scanning for credential shapes, then test each candidate against the issuing service to confirm it is live and what it can do. The report lists each key, the service, its scope and whether it can spend money.
Fix direction
Call paid services from a server-side function (an API route, Edge Function or Cloud Function) that holds the key as an environment variable, a setting stored outside the code. The browser calls that function instead of the provider. Revoke the exposed key at the provider and issue a new one.
Mechanism documented in: Secrets Management Cheat Sheet (verified 2026-09-21); How to use environment variables in Next.js (verified 2026-09-21).
Covered by
Pre-launch check ($490, 48 hours) and Security sweep ($290, 24 hours)
Both include a re-check after your fixes.
Related patterns
- Service-role key shipped in the browser bundleSecrets and keysCritical
Anyone who opens the app can copy the key from the downloaded JavaScript and read, change or delete every row in every table.
- NEXT_PUBLIC_ prefix on a secretSecrets and keysCritical
The build writes the secret's value into public JavaScript, so anyone who loads the site can read it, and a redeploy with the same variable name republishes it.
- LLM API key exposed to the clientAI featuresCritical
Anyone who views the page source can copy the key and run their own workloads on your account until the bill or the provider stops them.
- No spend cap on model callsAI featuresHigh
A script can hit the route in a loop overnight and the bill lands on your card, or the provider pauses your account mid-day when its own cap trips and every user sees errors.
Questions
can people see api keys in javascript
Yes. Every JavaScript file the browser downloads is readable by the person using the browser, through the developer tools or by saving the page. Building or minifying the code makes it harder to read, not hidden. A key that has to stay private belongs on a server that the browser talks to, never in the code the browser runs.
which api keys are ok to put in frontend code
Only keys the provider designs to be public, such as a Stripe publishable key, a Firebase web config, or a Supabase anon or publishable key. These are restricted on the provider's side so that holding them grants little on their own. Any key described as secret, private, server or admin needs to stay server-side.
how do i check if my api key was leaked
Search your live app's loaded scripts in the browser's Sources tab for the key prefix, and check the provider's dashboard for usage you do not recognise. If you find the key in the browser, revoke it at the provider first, then move the call to a server-side function that reads the new key from an environment variable.
Back to the catalogue, or run the self-check for your stack.