Fix guide · critical · stripe_webhook_secret

Stripe webhook signing secret (whsec_) in client code

What this rule means

A string matching whsec_* was found in your deployed JavaScript.

Why it matters

The webhook signing secret is what proves an inbound webhook came from Stripe. With it, an attacker can forge webhook events — payment_intent.succeeded, customer.subscription.created, etc. — that your server happily accepts as legitimate.

How to fix it

  1. Roll the webhook secret. Stripe Dashboard → Developers → Webhooks → click your endpoint → "Roll signing secret".
  2. Update server-side env (STRIPE_WEBHOOK_SECRET, no public prefix).
  3. Verify every webhook with constructEvent before processing:

Next.js Route Handler:

// app/api/stripe/webhook/route.ts
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
export async function POST(req: Request) {
  const sig = req.headers.get('stripe-signature')!;
  const body = await req.text();
  let event;
  try {
    event = stripe.webhooks.constructEvent(body, sig, process.env.STRIPE_WEBHOOK_SECRET!);
  } catch {
    return new Response('Invalid signature', { status: 400 });
  }
  // safe to handle event
}

Express:

const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  let event;
  try {
    event = stripe.webhooks.constructEvent(req.body, req.headers['stripe-signature'], process.env.STRIPE_WEBHOOK_SECRET);
  } catch {
    return res.status(400).send('Invalid signature');
  }
  // ...
});

Hono / Cloudflare Workers:

app.post('/webhook', async (c) => {
  const sig = c.req.header('stripe-signature')!;
  const body = await c.req.text();
  const event = await stripe.webhooks.constructEventAsync(body, sig, c.env.STRIPE_WEBHOOK_SECRET);
  // workers requires the async variant for Web Crypto
});
  1. Audit webhook deliveries in the Dashboard for events that didn't originate from your customers' real activity.

Did vibecheck flag this on your app?

If you reached this page from a vibecheck inspection report, the redacted match in your scan output is the exact string we found in your bundle. After applying the fix above, run the inspection again — the finding should clear.

Run another inspection