fix(security): require STRIPE_WEBHOOK_SECRET for webhook signature verification

VULN-001: Remove insecure fallback that allowed processing webhooks without
signature verification when STRIPE_WEBHOOK_SECRET was not set.

Changes:
- Add startup check that exits with error if STRIPE_WEBHOOK_SECRET is missing
- Remove JSON.parse fallback that bypassed signature verification
- Always use stripe.webhooks.constructEvent() for webhook validation

This prevents attackers from forging webhook events to manipulate
orders, subscriptions, or other payment-related data.
This commit is contained in:
Sergei 2026-01-26 16:41:54 -08:00
parent d453126c89
commit a74d6d5e92

View File

@ -3,6 +3,14 @@ const router = express.Router();
const Stripe = require('stripe');
const { supabase } = require('../config/supabase');
// SECURITY: Require STRIPE_WEBHOOK_SECRET in production
if (!process.env.STRIPE_WEBHOOK_SECRET) {
console.error('❌ FATAL: STRIPE_WEBHOOK_SECRET is required!');
console.error(' Webhook signature verification cannot be disabled.');
console.error(' Get your webhook secret from: https://dashboard.stripe.com/webhooks');
process.exit(1);
}
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
/**
@ -18,14 +26,8 @@ router.post('/stripe', async (req, res) => {
let event;
try {
// If webhook secret is configured, verify signature
if (webhookSecret) {
// SECURITY: Always verify webhook signature
event = stripe.webhooks.constructEvent(req.body, sig, webhookSecret);
} else {
// For local development without webhook secret
event = JSON.parse(req.body.toString());
console.warn('⚠️ Webhook signature verification skipped (no STRIPE_WEBHOOK_SECRET)');
}
} catch (err) {
console.error('Webhook signature verification failed:', err.message);
return res.status(400).send(`Webhook Error: ${err.message}`);