Stripe Secret Key Exposure
Billing Safety · BIL-01 · Priority: P0
Why It Matters
The Stripe secret key (sk_live_ or sk_test_) grants full API access to your Stripe account — including the ability to issue refunds, create charges, read customer payment methods, cancel subscriptions, and export all transaction data. If this key appears in client-side code, any visitor to your app can extract it from the browser bundle.
AI code generators frequently place Stripe keys in shared utility files or React components without distinguishing between the publishable key (pk_) and the secret key (sk_). The publishable key is safe for the browser — the secret key is not.
Priority: P0 — Equivalent to giving anyone your Stripe dashboard password.
Affected Stack: Next.js + Stripe, any framework with Stripe integration
The Problem
AI tools create a Stripe client in a shared module and import it everywhere — including client components. The secret key ends up in files bundled for the browser.
// ❌ What AI tools typically generate
import Stripe from 'stripe';
// This file is imported by both server and client code
export const stripe = new Stripe(process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY!);
Common patterns that expose the key:
NEXT_PUBLIC_STRIPE_SECRET_KEYin.env(NEXT_PUBLIC_ = bundled in browser)sk_live_orsk_test_hardcoded in source files- Stripe client initialized in a shared
lib/file imported by React components
The Fix
The Stripe secret key must only exist in server-side code. Use environment variables without the NEXT_PUBLIC_ prefix.
// ✅ Server-only Stripe client
// app/api/stripe.ts (never imported by client components)
import Stripe from 'stripe';
export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: '2024-12-18.acacia',
});
# ✅ .env — no NEXT_PUBLIC_ prefix for secrets
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_... # This one is safe
After fixing: Rotate the exposed key immediately in the Stripe dashboard. Any previously deployed build may have the old key cached.
References
Related Checks
- NEXT_PUBLIC_ Secret Exposure — AUTH-05
- Stripe Webhook Safety — BIL-02
- Server-Initiated Checkout — BIL-14
Is your app safe? Run Free Scan →