Skip to content

Case Study: Zero-Trust Webhook Ingress (Stripe & GitHub) ​

This case study demonstrates how to protect payment gateways and webhook ingestion endpoints from unauthorized tampering, forged payload injection, and internal route disclosure.


The Threat Model ​

Modern SaaS and e-commerce applications rely heavily on external webhooks from services like Stripe, GitHub, Shopify, Paddle, and Slack.

Because webhook handlers must be reachable over the public internet, developers frequently place their entire payment or integration microservice behind Traefik. This exposes several risks:

  • Reconnaissance of Internal Endpoints: Attackers probe /webhooks/debug, /webhooks/replay, or /webhooks/test.
  • Forged Event Injection: Direct HTTP spam to the webhook receiver attempting to trigger expensive verification workflows or crash background queues.
  • Credential & Config Exposure: Accidental leakage of .env or deployment configurations on webhook servers.

The Solution: Two-Layer Zero-Trust Defense ​

With RouteWarden, you enforce a two-tier gatekeeper at the edge:

  1. IP Range Restriction (allowedIps): Only official CIDR blocks published by Stripe/GitHub can send payloads to /webhooks/.*.
  2. Exact Allowlist (allowPatterns): Only designated production webhook endpoints (e.g. /webhooks/stripe/v1) are permitted; all internal or debug paths are blocked with 404 Not Found or dropped silently (silentDrop).

Configuration (Traefik, Caddy & NGINX) ​

# dynamic_conf.ymlhttp:  middlewares:    webhook-shield:      plugin:        routewarden:          enabled: true          enableDefaultPatterns: true          # Block everything under /webhooks by default          pathPatterns:            - '(?i)^/webhooks(/.*)?$'          # Allow ONLY the verified production webhook handler          allowPatterns:            - '(?i)^/webhooks/stripe/v1$'          # Restrict to official Stripe Webhook IP ranges          allowedIps:            - "3.18.12.63/32"            - "3.130.192.231/32"            - "13.235.14.237/32"            - "13.235.122.149/32"            - "35.154.171.200/32"          response:            mode: silentDrop # Drop unauthorized scanner connections immediately  routers:    webhook-router:      rule: "Host(`api.example.com`) && PathPrefix(`/webhooks`)"      entryPoints:        - websecure      middlewares:        - webhook-shield      service: webhook-service

Released under the MIT License.