Security Guide

5 Fouten bij Webhook Beveiliging

Real-time webhook debugging voor Nederlandse developers

Webhooks are the backbone of modern event-driven architectures. At WebhookWatch, we process over 2.4 million webhook deliveries per month for Dutch startups and agencies. Across that volume, one pattern stands out: security is the most common failure point. This article breaks down the five most critical webhook security mistakes we see in production โ€” and exactly how to fix each one.

Whether you're integrating with Stripe, GitHub, Shopify, or a custom internal service, the same vulnerabilities appear again and again. The cost of getting it wrong ranges from data leakage to full account takeover. Let's walk through every mistake, with code examples you can apply today.

๐Ÿ”“

Fout 1: Not Verifying Webhook Signatures

The single most common mistake. When you receive a webhook POST request, you must verify the signature header before processing the payload. Without signature verification, any attacker who discovers your endpoint can send forged events โ€” triggering fraudulent charges, creating fake orders, or injecting malicious data into your pipeline. Stripe sends a Stripe-Signature header, GitHub uses X-Hub-Signature-256, and Shopify provides X-Shopify-Hmac-Sha256. Each provider documents the exact HMAC algorithm and secret key format. Never skip this step, not even in staging.

๐ŸŒ

Fout 2: Exposing Webhook URLs in Public Repositories

Webhook endpoint URLs are effectively API keys. We've found live webhook URLs committed to GitHub repositories at least 47 times in the past quarter alone. When a URL is public, bots and scanners can discover it within hours. Always treat webhook URLs as secrets: store them in environment variables, use a secrets manager like AWS Secrets Manager or HashiCorp Vault, and rotate them immediately if they appear in a public commit. If possible, use a reverse proxy with IP allowlisting to add an extra layer of access control.

๐Ÿ”‘

Fout 3: Hardcoding Signing Secrets in Source Code

Even when developers implement signature verification, the signing secret is often hardcoded directly in the application code. A single const WEBHOOK_SECRET = 'whsec_abc123...' in a JavaScript file means every developer with repository access holds a copy of your secret. If that repository becomes public โ€” through an accidental open-source push or a leaked fork โ€” your entire webhook infrastructure is compromised. Use environment variables for local development, and a dedicated secrets management service for production deployments.

๐Ÿ”„

Fout 4: Missing Idempotency and Duplicate Handling

Reliable webhook providers like Stripe and GitHub will retry failed deliveries. If your endpoint returns a non-2xx status code, the same event arrives again โ€” sometimes dozens of times. Without idempotency checks, a single payment event could trigger three invoice creations, three database writes, or three customer notifications. Store a unique event ID from the payload and check against your database before processing. Use database-level unique constraints or a Redis set with TTL for fast duplicate detection. Always respond with 200 OK as quickly as possible, then process the event asynchronously.

โฑ๏ธ

Fout 5: No Timeout Handling or Request Validation

Webhook endpoints must respond within 5โ€“10 seconds, depending on the provider. If your endpoint performs a slow database query, calls an external API, or processes heavy data before sending a response, the provider will mark the delivery as failed and retry. This creates a cascade: slow processing โ†’ timeout โ†’ retry โ†’ duplicate processing โ†’ even slower processing. The fix is architectural: acknowledge receipt with a 200 response immediately, then hand the payload to a message queue like RabbitMQ or AWS SQS for background processing. Additionally, validate the Content-Type header (should be application/json) and reject requests with unexpected or missing headers before any business logic runs.

Quick Reference: Signature Verification in Node.js

Here's a production-ready pattern for verifying Stripe webhook signatures. Adapt the header name and algorithm for your specific provider:

const crypto = require('crypto');

function verifyStripeSignature(payload, signature, timestamp, secret) {
  const signedPayload = `${timestamp}.${payload}`;
  const expected = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex');

  const sig256 = signature.split(',')[0].replace('sha256=', '');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(sig256)
  );
}

// Usage in Express
app.post('/webhooks/stripe', (req, res) => {
  const signature = req.headers['stripe-signature'];
  const valid = verifyStripeSignature(
    req.rawBody,
    signature,
    signature.split(',')[0].split('=')[1],
    process.env.STRIPE_WEBHOOK_SECRET
  );

  if (!valid) {
    return res.status(400).send('Invalid signature');
  }

  // Process event asynchronously
  queue.processEvent(req.body);
  res.status(200).send('OK');
});
73%
of audited endpoints skip signature verification
2.4M
webhooks processed monthly through WebhookWatch
<5s
maximum response time to prevent retries
47
public webhook URLs found in GitHub this quarter

About the Author

Daan de Vries is a senior backend engineer and founder of WebhookWatch. Based in Amsterdam, Daan has spent six years building event-driven integrations for companies like Mollie, Bol.com, and various Y Combiner-backed startups. He's personally debugged over 18,000 webhook delivery failures and maintains an open-source webhook signature verification library used by 3,200+ developers. When he's not tracing HTTP requests, he writes about API architecture on his personal blog.

Related Articles

๐Ÿ“ก

How to Build a Webhook Relay That Survives Outages

Designing resilient webhook infrastructure with dead-letter queues, exponential backoff, and automatic replay โ€” a complete architecture guide for production systems.

๐Ÿงช

Testing Webhooks Locally Without Exposing Your Machine

A comparison of ngrok, cloudflare tunnels, and WebhookWatch's built-in tunnel feature for safe local development. Includes setup instructions and security considerations.

๐Ÿ“Š

Webhook Delivery Metrics You Should Monitor in 2025

Beyond uptime: tracking latency percentiles, retry rates, signature failure counts, and payload size distributions to keep your integration pipeline healthy.