Secrets in the client bundle: how API keys leak from frontends

Here is a rule with no exceptions: anything shipped to the browser is readable by anyone with the browser. Your frontend bundle is not a vault, it is a public document. Yet API keys, tokens, and secrets end up in client-side code constantly, because doing so often makes the feature work in the demo, and the cost is invisible until someone goes looking.
How it happens
A developer needs the frontend to call a third-party service (a payments API, a maps provider, an AI model), so they put the key where the calling code is: in the client. It works immediately. The problem is that bundlers inline that key into the JavaScript every visitor downloads, and anyone can open developer tools, read the network requests, or grep the bundle and walk away with it. This is cataloged as a hardcoded-credentials weakness, CWE-798, and it is depressingly common.
There is no such thing as a hidden value in client-side code. If the browser can use it, an attacker can read it. Obfuscation just slows down the curious.
Why AI-assisted code makes it worse
An AI coding assistant asked to wire up a third-party call will happily put the key inline, because that is the most direct way to make the code run. The model optimizes for code that runs, and a key in the client runs perfectly, so the leak only shows up when an adversary goes looking. It is the same dynamic behind a whole family of AI-generated security mistakes, which we cover in what AI-generated code gets wrong about security.
How to do it right
- Keep secrets on the server. Have the browser call your backend, and your backend call the third party with the key.
- Use a backend proxy or serverless function for any third-party API that requires a secret.
- Where a provider supports it, use publishable or restricted client keys that are safe to expose and scoped to do only what the frontend needs.
- Scan your built bundle and your git history for secrets, and rotate anything that ever shipped to a client.
Finding exposed secrets is part of what a real test does: Uvy inspects what your application actually ships to the client and proves where a secret is reachable, with the exact request that retrieves it. See how it works.