GeneralCritical

Exposed Payment Keys

Stripe secret keys or other payment processor credentials found in client-side code.

Last updated 2026-01-15

What Is This Vulnerability

Exposed Payment Keys is a critical vulnerability where secret API keys for payment processors — primarily Stripe, but also Braintree, Square, PayPal, or Adyen — are found in client-side JavaScript bundles, public repositories, or frontend source code. Payment processors provide two types of keys: publishable keys (safe for client use) and secret keys (server-only). This vulnerability specifically concerns the exposure of secret keys that grant full API access.

Stripe secret keys follow the pattern sk_live_... (production) or sk_test_... (sandbox). While test keys have limited impact, live secret keys provide complete access to the payment account.

Why It's Dangerous

An exposed Stripe secret key grants an attacker complete control over your payment operations:

  • Refund fraud — issue refunds on legitimate charges, stealing revenue directly.
  • Customer data access — read all customer records including names, emails, addresses, and partial card numbers.
  • Create charges — charge stored payment methods for arbitrary amounts.
  • Transfer funds — on Connect platforms, transfer funds to attacker-controlled accounts.
  • Subscription manipulation — cancel, modify, or create subscriptions.
  • Payout redirection — modify payout settings to redirect funds to attacker bank accounts.
  • PCI compliance violation — exposed payment keys may trigger PCI DSS obligations and regulatory consequences.

The financial impact is immediate and direct. Attackers can drain funds within minutes of discovering the key.

How to Detect

Search for payment key patterns in client-side code:

// In browser DevTools — Sources tab, search all files:
// Stripe secret keys (CRITICAL if found)
sk_live_[a-zA-Z0-9]{24,}
sk_test_[a-zA-Z0-9]{24,}

// Stripe restricted keys
rk_live_[a-zA-Z0-9]{24,}

// Check network requests for server-side API calls from the browser
// If you see requests to api.stripe.com with a secret key in
// the Authorization header, the key is exposed
fetch('https://api.stripe.com/v1/charges', {
  headers: {
    'Authorization': 'Bearer sk_live_...'  // CRITICAL: exposed in browser
  }
});

// Also check environment variable leaks in Next.js / React bundles
// Keys without NEXT_PUBLIC_ prefix should NOT appear in client bundles
console.log(process.env.STRIPE_SECRET_KEY); // leaked if visible in bundle

AuditYour.app scans all JavaScript bundles and network requests for payment processor key patterns. It distinguishes between publishable keys (expected in client code) and secret keys (critical finding).

How to Fix

Ensure all payment operations happen server-side:

// Client-side: use ONLY the publishable key
import { loadStripe } from '@stripe/stripe-js';
const stripe = await loadStripe('pk_live_...');  // Publishable key is safe

// Server-side API route: create payment intents with the secret key
// /app/api/create-payment-intent/route.ts
import Stripe from 'stripe';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!); // Server only

export async function POST(request: Request) {
  const session = await getServerSession();
  if (!session) return Response.json({ error: 'Unauthorized' }, { status: 401 });

  const { amount, currency } = await request.json();

  const paymentIntent = await stripe.paymentIntents.create({
    amount,
    currency,
    customer: session.user.stripeCustomerId,
    automatic_payment_methods: { enabled: true },
  });

  // Only return the client_secret, never the full PaymentIntent
  return Response.json({ clientSecret: paymentIntent.client_secret });
}

If a secret key has been exposed:

  1. Roll the key immediately in the Stripe Dashboard under Developers > API Keys.
  2. Audit recent activity — check the Stripe Dashboard for unauthorized refunds, charges, transfers, or customer data access.
  3. Review framework configuration — in Next.js, ensure the key variable does NOT start with NEXT_PUBLIC_. In Vite, ensure it does NOT start with VITE_.
  4. Enable Stripe Radar and set up webhook alerts for unusual activity.

Scan your app for this vulnerability

AuditYourApp automatically detects security misconfigurations in Supabase and Firebase projects. Get actionable remediation in minutes.

Run Free Scan