Critical severity · Next.js

Exposed Stripe secret key on Next.js

A Stripe secret key (starts with `sk_live_` for production, `sk_test_` for test) is in your client code. This key can create charges, issue refunds, access customer data, and modify products. Treat this as a five-alarm incident: (1) rotate in Stripe dashboard immediately; (2) check Stripe logs for unauthorized use; (3) move all Stripe calls to server-side; (4) on client, only use the Publishable Key (`pk_live_...`), which is safe.

The fix for Next.js

Next.js

Stripe secret key goes server-side only. Client uses publishable key via @stripe/stripe-js.

// app/api/checkout/route.ts — SERVER
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);  // NOT NEXT_PUBLIC_

// client side:
import { loadStripe } from '@stripe/stripe-js';
const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!);

Why it matters

Stripe keys are some of the most targeted. GitHub scan feeds, bundle scrapers, and browser extensions all hunt for them. A leaked sk_live is drained in hours.

Confirm the fix worked

Scan your Next.js site to confirm this finding is gone.

AI prompt

Apply across your codebase

Paste this into Cursor, Lovable, Bolt, v0, or Claude Code.

My Stripe secret key (sk_live_ or sk_test_) is in my client bundle. This is critical. Walk me through: (1) rotating in Stripe dashboard; (2) checking logs for unauthorized use; (3) moving every Stripe call to server-side; (4) replacing client usage with the publishable key only. Also set up a webhook signing secret verification on my webhook handler if I have one.

FAQ

Frequently asked questions

What if it was only sk_test_?
Still rotate. Test keys can create test charges (which do not move real money) but can expose your customer email addresses and test data. Rotate and investigate.
I use Stripe Checkout — do I need server code?
Yes. Even Checkout requires creating a Session with your secret key on the server, then redirecting the user to the returned URL.