Worked example / Lovable audit

Stripe webhook retries: when one event is delivered twice.

A synthetic example of how a payment finding is evidenced, bounded and turned into a useful next action. No customer system was assessed for this article.

Illustrative scenario. The names, event IDs and behavior below are fabricated to demonstrate an audit method. They are not a verified vulnerability in Lovable, Stripe or any customer app.

The question

A Lovable-built storefront uses a server endpoint to fulfill an order after receiving a Stripe checkout.session.completed event. The application marks the order paid and sends an onboarding email. What happens if Stripe delivers the same event again?

A successful first payment proves only the happy path. Webhook delivery can be retried, so the handler should treat the event ID as a durable unit of work. An HTTP 200 response is not enough evidence that repeat delivery is safe.

What a scoped review would inspect

  1. Event authentication: verify the Stripe signature against the raw request body and the configured endpoint secret before trusting the payload.
  2. Event identity: locate where the Stripe event ID is persisted. A process-local variable or client-side flag cannot protect a second worker or a later retry.
  3. Transaction boundary: determine whether recording the event and updating the order are atomic. A crash between those writes can leave a paid order without a completed fulfillment record.
  4. Fulfillment effects: inspect whether emails, entitlement creation and inventory changes are safe when called twice.

Synthetic evidence

Assume an illustrative handler verifies the signature, then calls fulfillOrder(session.id) without recording event.id. In a controlled test environment, the same signed event is replayed twice. The example order receives one payment but two fulfillment rows and two emails.

That evidence supports a narrow finding: repeated webhook delivery can duplicate this fulfillment path. It does not prove that every payment path is affected, nor that Stripe created two charges.

Recommendation and verification

Record the event ID under a database uniqueness constraint and apply the order transition inside a transaction. Make downstream effects idempotent or dispatch them from a durable outbox. Replaying the same event should leave one order transition, one entitlement and one user email. Simulate a failure after each relevant step to check recovery.

For an audit without permission to replay production events, inspect the code, migrations and existing tests; state that runtime duplication is unverified until the team runs the controlled test.

Why this belongs in a report

The finding links a specific code path to a commercial consequence and gives an executable verification plan. That is more useful than a generic “add tests” warning. Priority depends on whether the handler actually grants access, ships goods or only updates analytics.