The risk of unverified webhooks

When integrating with Paystack, Flutterwave, or Stripe, the payment flow is asynchronous. The user completes the transaction on the provider's page, and the provider sends an HTTP POST request (the webhook) to your server to confirm the status.

If your server processes that payload without cryptographically verifying its origin, anyone who discovers the endpoint URL can send a POST request formatted to look like a successful payment. This bypasses the actual payment gateway entirely.

Signature Forgery

Attackers send payloads to your webhook endpoint without the correct HMAC signature. If your application doesn't validate the signature, the fake payment is processed.

Replay Attacks

An attacker intercepts a legitimate, signed webhook and resends it multiple times. If your system lacks idempotency, it credits the user repeatedly.

Timing Attacks

Attackers analyze the response time of your signature verification logic to guess the expected signature byte by byte. Use constant-time string comparison to prevent this.

Mandatory mitigation: HMAC signature verification

Payment providers publish a signing method for their webhooks. Many use an HMAC over the raw body and place the result in a request header, such as `x-paystack-signature`. Use the provider's current method and compare signatures without leaking timing data.

Are your payment webhooks vulnerable to forgery or replay attacks?

Discuss webhook testing

Defending against replay attacks

Even with perfect signature validation, a valid webhook can be intercepted and resent. To prevent a single ₦10,000 payment from crediting a wallet ten times, you must implement idempotency.

Use the unique transaction reference or event ID provided in the webhook payload as an idempotency key. Before processing the event, check your database or a distributed cache (like Redis). If the key has already been processed, respond with a 200 OK but skip the business logic.

How we test webhook security

During an API security assessment, our engineers actively attempt to break webhook integrations using several techniques:

The Implementation Gap

Verification as a middleware, not a suggestion

A common vulnerability pattern we see in Nigerian fintechs is placing the signature verification logic inside the controller, where it occasionally gets bypassed by new routes or refactoring. Signature validation should be implemented as a strict middleware that drops invalid requests before they ever reach your business logic.

Related reading

Blog: Payment gateway penetration testing · BOLA in payment APIs · Fintech API Security: 10 Steps

Services: API Security Testing · Penetration Testing

Industries: Payment Gateways

Frequently asked questions

Why can't I just trust the IP address sending the webhook?

No. An allowlist can narrow the source network, but it does not prove who created the payload. Verify the provider's cryptographic signature against the raw request body and reject failed checks.

What happens if a webhook is processed twice?

Without idempotency keys, processing a 'payment_successful' webhook twice could result in crediting a user's wallet twice for a single payment. Idempotency ensures duplicate notifications are safely ignored.

How do attackers discover my webhook endpoint?

Webhook endpoints are often exposed in client-side code, guessed through directory enumeration, or discovered if an attacker registers a test account on your platform and observes the callback structure.