From a74d6d5e92b385f508254bb405d759dded7e50ed Mon Sep 17 00:00:00 2001 From: Sergei Date: Mon, 26 Jan 2026 16:41:54 -0800 Subject: [PATCH] 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. --- backend/src/routes/webhook.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/backend/src/routes/webhook.js b/backend/src/routes/webhook.js index 6e04f23..b1e7577 100644 --- a/backend/src/routes/webhook.js +++ b/backend/src/routes/webhook.js @@ -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) { - 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)'); - } + // SECURITY: Always verify webhook signature + event = stripe.webhooks.constructEvent(req.body, sig, webhookSecret); } catch (err) { console.error('Webhook signature verification failed:', err.message); return res.status(400).send(`Webhook Error: ${err.message}`);