Skip to content
BuildThenTestedSee packages

Third-party API key in the JavaScript bundle

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. API keys and passwords the app uses to talk to other services. Check it yourself with the steps below; our test adds what a script and a second account can find.

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 }),
})
A paid third-party service called straight from a browser component, with the account's API key written into the request.

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.

  1. Open your live app in Chrome, right-click, choose Inspect, then open the Sources tab.
  2. Press Ctrl+Shift+F (Cmd+Option+F on a Mac) to search all loaded files. Search for Bearer, api_key, apiKey, sk_live, sk-, AKIA and secret.
  3. 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.
  4. 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.

Compare packages

Related patterns

  • Service-role key shipped in the browser bundleSecrets and keys

    Anyone who opens the app can copy the key from the downloaded JavaScript and read, change or delete every row in every table.

    Critical
  • NEXT_PUBLIC_ prefix on a secretSecrets and keys

    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.

    Critical
  • LLM API key exposed to the clientAI features

    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.

    Critical
  • No spend cap on model callsAI features

    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.

    High

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.