Run a threat model on a new payment integration: our service calls a third-party payment provider and receives webhooks. Where are the interesting threats?
Show the full answer Hide the answer
Draw the boundaries first
Three trust boundaries, and nearly every interesting threat lives on one of them:
- User → our service (untrusted input, authenticated session)
- Our service → payment provider (outbound, credentialed)
- Payment provider → our webhook endpoint (inbound, internet-facing, unauthenticated by default)
The third is the one teams under-protect, because it feels like it comes from a trusted party — and it arrives over the public internet from anyone who knows the URL.
Walking STRIDE across the webhook boundary
Spoofing — anyone can POST to the endpoint claiming a payment succeeded. Mitigation: verify the provider's signature over the raw body with the shared secret, before parsing. Not IP allow-listing alone, which providers change.
Tampering — modifying the amount or status in transit. Same mitigation; the signature must cover the exact bytes, which is why the raw body must be captured before any middleware reformats it.
Repudiation — no record of what was received. Mitigation: log every webhook with its signature-verification result, retained.
Information disclosure — error responses revealing internal state, or webhook payloads containing card data landing in application logs.
Denial of service — the endpoint is public, so it can be flooded. Mitigation: rate limit, accept-and-enqueue rather than processing inline.
Elevation of privilege — a webhook for order A used to mark order B as paid. Mitigation: validate that the referenced object belongs to the claimed context.
The threats specific to payments
Replay. A legitimate captured webhook resent repeatedly. Signature verification passes because it is legitimate. Mitigation: timestamp in the signed payload with a tolerance window, plus idempotent handling on the event ID.
Out-of-order delivery. A payment.succeeded arriving after a payment.refunded and overwriting it.
Mitigation: sequence numbers or timestamps, and state transitions that reject regressions.
Trusting the webhook as the source of truth. The strongest control: on receiving a webhook, call the provider's API to confirm the current state rather than acting on the payload. A forged or replayed webhook then achieves nothing.
Outbound credential compromise on boundary 2 — the API key. Mitigation: secrets manager, restricted scope, rotation, and egress restriction so it cannot be used from outside your network.
What a strong answer adds
Naming the idempotency requirement as a correctness issue as well as a security one: webhooks are at-least-once, so duplicate delivery is normal, and a handler that charges or ships on each delivery is broken regardless of any attacker. The security control and the reliability control are the same mechanism here.