Skip to content
Vibe Coding Best Practices
Security Foundations10 min read

Keep secrets and environment variables out of the browser

How to review AI-generated apps for exposed API keys, unsafe environment variables and client-side secret leaks before launch.

Beginnerrg "API_KEY|SECRET|TOKEN|PRIVATE_KEY"rg "NEXT_PUBLIC_|VITE_|PUBLIC_"git status --short

If a secret reaches the browser, it is not a secret.

This is one of the most common mistakes in AI-built apps because generated examples often optimise for "make it work" rather than "make it safe."

The app calls an API. The API needs a key. The easiest path is to put the key where the frontend can reach it.

That path works.

It also leaks the key to every user who opens DevTools.

What counts as a secret

Treat these as server-only unless you know otherwise:

  • private API keys
  • Stripe secret keys
  • database URLs
  • service role keys
  • JWT signing secrets
  • webhook secrets
  • OAuth client secrets
  • admin tokens
  • email provider keys
  • AI provider keys
  • object storage write tokens

Some values are intentionally public, such as publishable Stripe keys or analytics site IDs. Public does not mean harmless, but it does mean the provider designed them to be visible.

If you are unsure, assume server-only.

Understand public prefixes

Many frontend frameworks expose environment variables with specific prefixes.

In Next.js, variables starting with NEXT_PUBLIC_ are bundled for the browser.

In Vite, variables starting with VITE_ are exposed.

That means this is dangerous:

NEXT_PUBLIC_OPENAI_API_KEY=sk-...
NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEY=...

The prefix made the secret public.

Use this search:

rg "NEXT_PUBLIC_|VITE_|PUBLIC_"

Then ask:

Review every public environment variable in this app.

For each one:
- explain whether it is safe to expose to the browser
- identify where it is used
- say whether it should be moved server-side
- propose the safest replacement pattern

Search for obvious secret names

Run:

rg "API_KEY|SECRET|TOKEN|PRIVATE_KEY|SERVICE_ROLE|DATABASE_URL|WEBHOOK"

This will produce false positives. That is fine.

The goal is to find values and code paths that deserve review.

Use this prompt:

Audit these search results for secret exposure.

Flag anything that:
- appears in client code
- is prefixed as public
- is logged
- is returned in an API response
- is committed to the repo
- is passed into a component rendered in the browser

Explain the fix for each issue.

Check your git state

Before committing or deploying, run:

git status --short

Look for files like:

  • .env
  • .env.local
  • credentials.json
  • service account files
  • exported database dumps
  • generated debug logs

If a secret file is untracked, do not commit it.

If a secret was already committed, deleting the file is not enough. Rotate the secret.

The safe proxy pattern

If the browser needs to trigger an action that requires a secret, the browser should call your server. Your server should call the third party.

Unsafe:

Browser -> OpenAI with secret key

Safer:

Browser -> your API route -> OpenAI with server-side key

The browser never receives the secret.

Ask your agent:

Find any frontend code that calls third-party APIs directly.

For each call, identify whether it uses a secret, token, or privileged endpoint.
If it does, propose a server-side proxy route that validates input, applies rate limiting, calls the third party, and returns only the fields the UI needs.

Verify in the browser

After fixing, verify from the outside:

  1. Open the app in a browser.
  2. Open DevTools.
  3. Search the JavaScript bundle and network requests for secret-looking values.
  4. Submit the main forms.
  5. Inspect request payloads and responses.

You are looking for anything that feels like a credential, token or privileged identifier.

What PageLens can help with

PageLens can catch some public symptoms of unsafe launches, especially around exposed routes, security posture, headers, and client-side implementation signals.

It cannot prove every secret is safe inside your repo. That requires code review.

Use both:

  • code search for source-level secrets
  • browser inspection for bundled leaks
  • PageLens for public launch-readiness signals

Secrets are binary. Either they are private or they are not.

Do not launch until you know which side you are on.

Keep secrets and environment variables out of the browser | PageLens AI