← Learn

Definition

Why isn't an environment variable enough to hide a secret?

An environment variable keeps a secret out of your source code and git history, but it does not make the secret private if the code that reads it runs in the browser. Anything used in client-side code, including any value a framework marks as public, is bundled and shipped to every visitor. A secret is only hidden if it is read and used on the server.

What env vars actually do

They move the value out of committed source. That solves the git-history leak, which is real and worth solving, but it is only half the problem. Where the value is used matters as much as where it is stored.

The browser is public

In Next.js, a NEXT_PUBLIC_ prefix inlines the value into the client bundle. In Vite, import.meta.env values used in components ship too. Any secret referenced in client code can be read from the browser, no matter how you stored it. Secret keys must be used only in server code.

What this means for AI-generated code

AI assistants often fix a client-side undefined-variable error by adding a public prefix, which quietly ships the secret to the browser. The code works, so the leak is invisible until someone reads the bundle. Keep secret keys in server components, route handlers, or server actions only.

Want to know if your app has this issue? Scan a public repo free, no account needed.

Scan a repo →

Related: how this happens in v0 / Next.js

Client-Side vs Server-Side Secrets: Why env Vars Aren't Enough: Prbl