Securing Webhooks: Top 10 Vulnerabilities to Avoid
The ten most common webhook security mistakes and how to fix them: signature bypass, replay attacks, SSRF, secrets in logs, and more.
Ozer
Developer & Founder of HookSense
Webhooks are a privileged channel into your system. A malicious or replayed webhook can move money, change permissions, or trigger emails to your customers. Securing them is non-negotiable.
Here are the ten most common webhook security mistakes — and how to fix them — based on real production incidents.
1. Non-timing-safe signature comparison
The classic. You're verifying HMAC signatures, but you compare with ===:
// VULNERABLE
if (expected === provided) { /* accept */ }
This leaks timing information. An attacker can measure response times and incrementally guess the signature byte-by-byte. Always use a constant-time comparison:
// SAFE
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(provided));
2. Verifying the parsed body instead of raw bytes
Most signatures are computed over the raw HTTP body, not the deserialized JSON. If your middleware parses JSON before your verification code runs, you're re-serializing — and a single byte difference (key order, whitespace) breaks the signature.
Fix: configure body-parser to keep the raw body, or use a raw-body middleware on webhook routes specifically.
3. Missing replay-attack protection
A signed webhook proves authenticity but not freshness. If an attacker captures a valid signed payment-succeeded event and re-sends it tomorrow, your handler will accept it.
Defense: reject events with timestamps older than 5 minutes (most providers include a timestamp in the signature). And make handlers idempotent so even in-window replays don't cause duplicate side effects.
4. Trusting the URL as the security boundary
"The webhook URL is secret" is not a security model. URLs leak in logs, error tracking, browser history, screenshots. Treat the URL as public knowledge; rely on signature verification for security.
5. Logging webhook payloads with secrets
Webhooks sometimes contain tokens, API keys, PII. If you log raw payloads to your error tracker or aggregated logs, you've widened your blast radius. Redact known sensitive fields before logging, or log only event metadata (ID, type, timestamp) — not the full body.
6. SSRF in replay/forwarding logic
If your system lets users configure a "forward this webhook to URL X" feature, you've built an SSRF gadget. An attacker could point the URL at http://169.254.169.254/ (AWS metadata) or internal services.
Defense: validate the target URL against an allow-list or block private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16, ::1, fe80::/10). HookSense does this for the Replay feature.
7. Accepting webhooks before verification
Some teams return 200 OK before they've finished verifying the signature, hoping to avoid timeouts. The risk: an attacker who knows you ack-then-verify can flood your endpoint with fake events to exhaust resources. Always verify first, then ack.
8. Sharing signing secrets across environments
Using the same signing secret for production and staging means a leaked staging secret compromises production. Generate a separate secret per environment (and ideally per endpoint).
9. No rotation strategy
You'll eventually need to rotate a signing secret — leaked credential, employee offboarding, scheduled rotation. If your handler accepts only one secret, rotation requires downtime. Configure your handler to accept multiple valid secrets temporarily, phase out the old one after the next provider-side rotation.
10. Not auto-disabling failing endpoints (sender side)
If you're sending webhooks to customer URLs, an attacker can register your-app.com's webhook URL as their endpoint and capture all traffic meant for that customer. Mitigations: domain verification on URL registration, auto-disable endpoints after consistent failures (so attackers can't keep failed endpoints alive indefinitely), and never include sensitive data in webhook bodies that the receiver doesn't already know.
Quick security checklist
- ✅ Signatures verified with
timingSafeEqual - ✅ Raw body used for verification, not parsed JSON
- ✅ Timestamp tolerance enforced (5 min default)
- ✅ Event IDs deduplicated for idempotency
- ✅ Payloads not logged verbatim — redact secrets
- ✅ Replay/forward URLs validated against private IP ranges
- ✅ Verify before ack, not after
- ✅ Per-environment, per-endpoint signing secrets
- ✅ Multi-secret support for rotation without downtime
- ✅ Auto-disable on consistent failure (outbound senders)
Further reading
Related posts
Try HookSense Free
Inspect, debug, and replay webhooks in real-time. No credit card required.
Get Started Free