Webhook Security: How to Protect Your Endpoints
Complete guide to webhook security. Learn about signature verification, IP allowlisting, rate limiting, and other security best practices.
Why Webhook Security Matters
Webhooks are a common attack vector. Without proper security, attackers can:
- Send fake events to manipulate your application
- Flood your endpoint with requests (DoS)
- Exploit vulnerabilities in your webhook handler
This guide covers essential webhook security practices.
1. Signature Verification
Most webhook providers sign their payloads. Always verify signatures before processing.
How Signatures Work
- Provider creates an HMAC hash of the payload using a secret key
- Hash is included in a header (e.g.,
X-Hub-Signature-256) - You compute the same hash and compare
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from('sha256=' + expected)
);
}
Provider-Specific Verification
Each provider has different signature schemes:
- Stripe:
stripe-signatureheader with timestamp - GitHub:
X-Hub-Signature-256header - Shopify:
X-Shopify-Hmac-SHA256header - Twilio: Signature in Authorization header
Hookbase verifies signatures automatically for 20+ providers.
2. IP Allowlisting
Restrict webhook endpoints to known provider IPs.
Provider IP Ranges
- Stripe: Publishes IP ranges in documentation
- GitHub: Available via API at
api.github.com/meta - Shopify: Available in documentation
Implementation
const allowedIPs = ['192.0.2.1', '192.0.2.2'];
app.post('/webhook', (req, res) => {
const clientIP = req.ip;
if (!allowedIPs.includes(clientIP)) {
return res.status(403).json({ error: 'Forbidden' });
}
// Process webhook
});
Caution: IP ranges change. Update your allowlist regularly.
3. Rate Limiting
Protect against DoS attacks with rate limiting.
const rateLimit = require('express-rate-limit');
const webhookLimiter = rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 100, // 100 requests per minute
message: 'Too many requests'
});
app.post('/webhook', webhookLimiter, handleWebhook);
4. HTTPS Only
Always use HTTPS for webhook endpoints. HTTP webhooks can be intercepted and modified.
Most providers require HTTPS endpoints in production.
5. Timeout Protection
Set timeouts to prevent slow requests from exhausting resources.
const timeout = require('connect-timeout');
app.post('/webhook', timeout('10s'), (req, res) => {
// Process webhook
});
6. Input Validation
Validate webhook payloads before processing.
const Joi = require('joi');
const stripeEventSchema = Joi.object({
id: Joi.string().required(),
type: Joi.string().required(),
data: Joi.object().required()
});
function validatePayload(payload) {
const { error } = stripeEventSchema.validate(payload);
if (error) {
throw new Error('Invalid payload');
}
}
7. Replay Attack Prevention
Use timestamps to prevent replay attacks. Reject events older than a few minutes.
function isRecentEvent(timestamp) {
const eventTime = new Date(timestamp * 1000);
const now = new Date();
const fiveMinutes = 5 * 60 * 1000;
return (now - eventTime) < fiveMinutes;
}
8. Secrets Management
Never hardcode webhook secrets. Use environment variables or a secrets manager.
// Bad
const secret = 'whsec_xxx';
// Good
const secret = process.env.WEBHOOK_SECRET;
9. Audit Logging
Log all webhook activity for security auditing.
function logWebhook(event, status) {
console.log({
timestamp: new Date().toISOString(),
eventId: event.id,
eventType: event.type,
sourceIP: request.ip,
status: status
});
}
10. Use a Webhook Gateway
A webhook gateway like Hookbase provides security features out of the box:
- Automatic signature verification for all major providers
- IP filtering
- Rate limiting
- Audit logging
- Payload validation with JSON Schema
Security Checklist
- [ ] Verify webhook signatures
- [ ] Use HTTPS only
- [ ] Implement rate limiting
- [ ] Validate payloads
- [ ] Log all webhook activity
- [ ] Use environment variables for secrets
- [ ] Set request timeouts
- [ ] Consider IP allowlisting
Conclusion
Webhook security requires multiple layers of protection. Start with signature verification, add rate limiting, and implement proper logging. Or use a webhook gateway like Hookbase to handle security automatically.