Back to Common risks

Common risksSecret keys

A live secret key in the code your app sends every visitor

If a secret key lands in client-side JavaScript, every person who loads your app can copy it. That includes bots that scan public repos and served bundles around the clock.

What can go wrong

A secret key is a password your app uses to talk to a service like Stripe, OpenAI, or Supabase on the server. It is not meant to be public.

When that key is imported into React, Next.js, or Vite client code, your build tool bundles it into JavaScript files the browser downloads. Anyone can open DevTools, read the bundle, or curl your deployed _next/static files and extract the key.

With a live Stripe sk_live_ key, a stranger can charge cards, issue refunds, or read payment data. With an AI provider key, they can run up your bill. Treat any key that was ever in client code as burned: rotate it with the provider, not just delete the line.

It happened for real

In early 2025, builders reported Cursor-generated React payment components that pasted a live Stripe secret key straight into client-side code. The pattern is common enough that Seatbelt hard-gates it on every Ship Read.

How to check yours

Seatbelt flags this automatically. A live secret key (sk_live_, sk_test_ used as if it were public, service_role, provider API keys) in client-reachable code is a must-fix hard gate. Publishable keys like Stripe pk_live_ belong in the browser; server secrets do not.

Ask your agent: "Search my repo for secret keys in any file that ships to the browser: sk_live, sk_test, OPENAI_API_KEY, service_role, sb_secret_. List file and line for each hit. Server-only secrets belong in server routes or environment variables the client bundle never imports."

We don't catch this yet: Keys that live only in hosting dashboard environment variables never appear in the repo export you hand us. Check your Vercel, Netlify, or Lovable deploy settings separately.

Fix direction

Move the secret to a server-only file (API route, server action, or edge function). Read it from process.env on the server. Never import a secret into a component marked "use client".

Paste into your agent: "Find any secret API keys referenced from client components. Move each call behind a server route that reads the key from environment variables. Rotate any key that was ever in client code."

Related risks