Skip to content
BuildThenTestedSee packages

NEXT_PUBLIC_ prefix on a secret

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. 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

# .env.local
NEXT_PUBLIC_SUPABASE_URL=https://abcd1234.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...   # fine: public by design
NEXT_PUBLIC_STRIPE_SECRET_KEY=sk_live_...   # inlined into the browser bundle
NEXT_PUBLIC_OPENAI_API_KEY=sk-proj-...
Server-only keys given the NEXT_PUBLIC_ prefix, which tells Next.js to copy their values into the JavaScript sent to every visitor.

What happens

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.

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

Check it yourself

Uses your builder's dashboard and your browser. No tools to install.

  1. In your hosting dashboard (Vercel: Project, Settings, Environment Variables) or your .env files, list every variable whose name starts with NEXT_PUBLIC_.
  2. For each one, ask whether the provider calls that value secret, private, server or admin. Stripe secret keys, model provider keys, database passwords and Supabase service_role keys all fall in that group.
  3. Open the live site in Chrome, right-click, choose Inspect, open the Sources tab and press Ctrl+Shift+F. Search for the first few characters of each suspect value.
  4. A bad result is a NEXT_PUBLIC_ variable holding a server-only key, or a search hit for that key's value in a loaded script.

What we check

We list every value inlined into the production bundle, match each to a provider and test whether it is live and what it can do. The report names the variable, where it appears in the built files and the scope it grants.

Fix direction

Remove the NEXT_PUBLIC_ prefix from the secret so it stays on the server, and read it only inside a Route Handler, Server Action or server component. Rotate the value, then redeploy so the new build no longer contains the old key.

Mechanism documented in: 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
  • Third-party API key in the JavaScript bundleSecrets and keys

    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.

    High
  • Secrets committed to the code repositorySecrets and keys

    Everyone who can see the repository, now or later, holds working keys to the database, payment account and model provider, and the keys stay in history after the file is deleted.

    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

Questions

are next_public environment variables secure

They are public by design. Next.js documents that a variable prefixed with NEXT_PUBLIC_ is inlined at build time into the JavaScript delivered to the browser, replacing each reference with the literal value. Use the prefix only for values meant to be public, such as a site URL or an anon key. Variables without the prefix stay on the server.

how do i keep an api key secret in next js

Store it as an environment variable without the NEXT_PUBLIC_ prefix and read it only in server code: a Route Handler, a Server Action or a server component. The browser calls your route, and your route calls the provider with the key. Next.js keeps non-prefixed variables out of the client bundle.

why is my env variable undefined in the browser next js

Because Next.js only exposes variables that start with NEXT_PUBLIC_ to browser code; everything else is server-only. Before adding the prefix, check whether the value is a secret. If it is, move the code that uses it to the server instead of exposing the variable.

Back to the catalogue, or run the self-check for your stack.