Webhook Security Essentials: Protecting Your Endpoints
Secure your webhook endpoints against common attacks. Learn about signature verification, IP whitelisting, and other security best practices.
HookWatch Team
December 28, 2025
Webhooks expose HTTP endpoints that anyone can call. Without proper security, attackers can send fake events to manipulate your application.
The 5 Security Essentials
1. Signature Verification
Most webhook providers sign payloads with a secret key. Always verify signatures to ensure the webhook is legitimate and hasn't been tampered with.
Javascript
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(expected)
);
}
2. HTTPS Only
Never expose webhook endpoints over plain HTTP. Always use HTTPS to encrypt payloads in transit, prevent man-in-the-middle attacks, and verify server identity.
Bash
# Redirect HTTP to HTTPS in nginx
server {
listen 80;
server_name api.yourapp.com;
return 301 https://$server_name$request_uri;
}
3. Payload Validation
Don't trust incoming data. Validate the structure and types before processing to prevent injection attacks and data corruption.
Javascript
function validatePayload(data) {
if (!data.event_type || typeof data.event_type !== 'string') {
throw new Error('Invalid event_type');
}
if (!data.data || typeof data.data !== 'object') {
throw new Error('Invalid data');
}
// Sanitize and validate nested fields
if (data.data.email && !isValidEmail(data.data.email)) {
throw new Error('Invalid email format');
}
}
4. IP Whitelisting
Some providers publish their webhook IP ranges. Whitelisting these IPs adds an extra layer of security by rejecting requests from unknown sources.
Javascript
const allowedIPs = [
'54.187.174.169', // Stripe
'54.187.205.235',
'54.187.216.72'
];
function isAllowedIP(ip) {
return allowedIPs.includes(ip);
}
app.use('/webhook', (req, res, next) => {
const clientIP = req.ip || req.connection.remoteAddress;
if (!isAllowedIP(clientIP)) {
return res.status(403).send('Forbidden');
}
next();
});
5. Rate Limiting
Protect against denial-of-service attacks by limiting how many requests can hit your webhook endpoint in a given time window.
Javascript
const rateLimit = require('express-rate-limit');
const webhookLimiter = rateLimit({
windowMs: 60 * 1000, // 1 minute window
max: 100, // 100 requests per minute
message: 'Too many webhook requests',
standardHeaders: true,
legacyHeaders: false,
});
app.use('/webhook', webhookLimiter);
How HookWatch Helps
HookWatch adds a security layer to your webhooks without writing security code yourself:
- Signature verification from major providers (Stripe, Shopify, GitHub)
- IP filtering based on provider-published ranges
- Rate limiting to prevent abuse
- Full audit logs for compliance and debugging
- Anomaly alerts when suspicious activity is detected
Secure your webhooks with HookWatch and focus on building your product.