fix(stripe): fail closed when webhook secret is unset (BUNYIP-203) #246

Merged
Claude-Run merged 1 commit from fix/bunyip-203-stripe-webhook-fail-closed into main 2026-06-26 07:11:07 +02:00
Member

The Stripe webhook handler called verify_webhook_signature unconditionally. When STRIPE_WEBHOOK_SECRET is unset, StripeConfig::from_env falls back to the public source literal whsec_placeholder, so anyone who knows that constant could forge a valid Stripe-Signature header and drive forged checkout/subscription/invoice events into membership activation, entitlement grants, and tier upgrades.

Add StripeService::webhook_secret_configured(), which returns false when the configured webhook secret is empty or equals the whsec_placeholder placeholder. The handler now consults it before verifying and returns 500 (fail closed) instead of verifying against the guessable placeholder, so an instance brought up without a real secret never trusts an event. main.rs logs a loud warning at startup when Stripe is otherwise wired but the webhook secret is missing. The placeholder literals are hoisted to named constants and reused by is_configured.

#BUNYIP-203

The Stripe webhook handler called verify_webhook_signature unconditionally. When STRIPE_WEBHOOK_SECRET is unset, StripeConfig::from_env falls back to the public source literal whsec_placeholder, so anyone who knows that constant could forge a valid Stripe-Signature header and drive forged checkout/subscription/invoice events into membership activation, entitlement grants, and tier upgrades. Add StripeService::webhook_secret_configured(), which returns false when the configured webhook secret is empty or equals the whsec_placeholder placeholder. The handler now consults it before verifying and returns 500 (fail closed) instead of verifying against the guessable placeholder, so an instance brought up without a real secret never trusts an event. main.rs logs a loud warning at startup when Stripe is otherwise wired but the webhook secret is missing. The placeholder literals are hoisted to named constants and reused by is_configured. #BUNYIP-203
fix(stripe): fail closed when webhook secret is unset (BUNYIP-203)
All checks were successful
E2E / Playwright against deployment (pull_request) Successful in 28s
Check / fmt + clippy + build + tests (pull_request) Successful in 9m2s
Create release / Create release from merged PR (pull_request) Has been skipped
be6e61a807
The Stripe webhook handler called verify_webhook_signature unconditionally. When STRIPE_WEBHOOK_SECRET is unset, StripeConfig::from_env falls back to the public source literal whsec_placeholder, so anyone who knows that constant could forge a valid Stripe-Signature header and drive forged checkout/subscription/invoice events into membership activation, entitlement grants, and tier upgrades.

Add StripeService::webhook_secret_configured(), which returns false when the configured webhook secret is empty or equals the whsec_placeholder placeholder. The handler now consults it before verifying and returns 500 (fail closed) instead of verifying against the guessable placeholder, so an instance brought up without a real secret never trusts an event. main.rs logs a loud warning at startup when Stripe is otherwise wired but the webhook secret is missing. The placeholder literals are hoisted to named constants and reused by is_configured.

#BUNYIP-203
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/bunyip!246
No description provided.