Safeguard
Security Guides•

Why do AI-built frontends leak API keys through env variables?

Frontend build tools copy prefixed env variables into browser code, so a secret in a prefixed variable is public. Learn the rule and how to fix it.

Safeguard Security Team
4 min read

Frontend build tools bundle certain environment variables into the JavaScript sent to every visitor. If an AI-generated app puts a secret key in one of those variables, the key becomes public. Keep secrets on a server, and expose to the browser only values that are safe to publish.

What the build tool actually does

Take Vite as an example. Its documentation says variables prefixed with VITE_ are exposed in client-side source code after bundling, and it advises avoiding that prefix to prevent accidentally leaking environment variables to the client. Its own example shows a VITE_SOME_KEY value reaching the browser while a DB_PASSWORD value does not. Other frameworks use their own prefixes with the same idea.

The prefix is a switch. It tells the tool "this value is meant for the browser." An AI assistant that wants an API call to work from the frontend may add the prefix to make the error go away, without noticing that it just published the key.

How the mistake happens

  1. The prototype calls a paid or privileged API directly from the browser.
  2. The call fails with "undefined key", because the variable is not exposed.
  3. The assistant renames the variable with the public prefix.
  4. The app works, and the key now sits in the bundle, readable in the browser's developer tools.

Nothing in that story looks like a security event. The app simply starts working.

Sorting values into two buckets

BucketExamplesWhere it can live
Safe to publishPublic site URL, analytics id, a key designed to be public and restricted by domainBrowser bundle
SecretPrivate API keys, database passwords, signing secrets, admin tokensServer only

Ask one question for every variable: if a stranger read this, what could they do? If the answer is "spend money" or "read data," it belongs on a server.

The fix pattern

Put a thin server endpoint between the browser and the provider. The browser calls your endpoint, your endpoint adds the secret and calls the provider, and it checks that the caller is allowed. This also gives you one place to add rate limits and logging.

If a secret already shipped in a bundle, treat it as exposed. Revoke or rotate it, deploy the fix, and check the provider's usage logs for activity you do not recognise.

Add a guard so it does not come back

  • Search the built output, not just the source, for the key's first characters after each build.
  • Add a rule to your assistant's instruction file: never put secrets in browser-exposed variables.
  • Review any pull request that touches environment files or adds a public prefix.
  • Keep an example environment file that marks each variable as public or secret.

The Twelve-Factor App offers a useful test: could the codebase be made open source at any moment without compromising credentials? Prototypes that pass it are safer to share and to promote.

Where Safeguard fits

Safeguard covers dependency scanning, reachability analysis, policies and gates, and compliance evidence. It does not replace the habit above, which is about where a value lives. Run a free scan of the project at gold.safeguard.sh/scan.

Quick check

Are all browser-exposed keys a problem?

No. Some keys are meant to be public and are restricted by domain or by scope. The problem is a secret key placed in a public variable.

Does minifying the bundle hide the key?

No. Minification shortens names but does not hide string values. Anyone can read them.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.