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
- The prototype calls a paid or privileged API directly from the browser.
- The call fails with "undefined key", because the variable is not exposed.
- The assistant renames the variable with the public prefix.
- 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
| Bucket | Examples | Where it can live |
|---|---|---|
| Safe to publish | Public site URL, analytics id, a key designed to be public and restricted by domain | Browser bundle |
| Secret | Private API keys, database passwords, signing secrets, admin tokens | Server 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.