You asked AI to wire up Stripe. Checkout works, the money lands, the webhook flips users to “paid.” You shipped it. What you actually shipped is an endpoint where anyone can unlock premium for free — without paying a cent.
What you shipped
A webhook is just a URL Stripe calls to say “this customer paid.” Your handler reads that message and upgrades the account. The problem is the handler believes the message without checking who sent it.

It reads the request body and acts on it. There’s no proof the request actually came from Stripe.
How anyone exploits it — no tools required
Your webhook URL isn’t secret; it’s in your code, your network tab, sometimes your docs. So an attacker just sends the same shape of request themselves:
POST /api/webhook
{ "type": "checkout.session.completed", "customer": "them" }
Your handler sees “payment completed,” upgrades the account, and never asks for a receipt. Free premium, on demand.
Why you won’t catch it in testing
Your real Stripe events work perfectly, so everything looks correct. The abuse is indistinguishable from a real payment — it just skips the payment. You usually find out when revenue doesn’t match the number of “paid” users.
Why AI skips it
Verifying a signature is an extra step that the happy path doesn’t need to “work.” AI optimizes for the shortest code that satisfies “handle the webhook,” and a handler that trusts the body does exactly that. The security step only matters against an adversary the prompt never mentioned.
The fix is one line
Verify the signature before trusting anything:

const event = stripe.webhooks.constructEvent(rawBody, signature, endpointSecret)
// throws if the request didn't really come from Stripe
Now a forged request is rejected before it can touch an account.
Check your app
- Every webhook endpoint (payments, subscriptions, usage, email) verifies the provider’s signature before acting.
- You’re verifying against the raw request body, not the parsed JSON (parsing first breaks signature checks).
- State changes are idempotent — the same event arriving twice doesn’t double-apply.
The bigger problem
A senior dev verifies webhook signatures by reflex. The trouble is that if nobody senior reads the code, the missing check ships — it works in every demo, right up until someone forges an event. The author and the reviewer are the same model with the same blind spot.
That’s the gap Velify is built to close: it reads your project and flags exactly this, in plain language, no terminal. Run it before your first customer does.
