Webhook Security Checklist (Ship It Without Getting Burned)
Webhook Security Checklist
Securing webhook endpoints prevents spoofing, abuse, and data breaches. This webhook security checklist signature verification retries idempotency lists the must-have controls for production webhook endpoints. This checklist covers signature verification, replay protection, rate limiting, and more to ensure your integrations are production-ready.
Baseline requirements (must-have)
This section is your webhook security checklist signature verification retries idempotency primer — implement these before going live.
Verify signature headers (X-SP-Timestamp, X-SP-Signature)
Always verify the X-SP-Timestamp and X-SP-Signature headers to ensure the request is authentic.
Use raw request body + constant-time compare
Generate the signature using the raw body and compare it using hash_equals to prevent timing attacks.
Enforce timestamp window (replay protection)
Reject requests where the timestamp is outside a ±5-minute window to prevent replay attacks.
Learn more about signature headers and delivery rules.
Common gotcha: Skipping timestamp validation can allow attackers to replay captured requests indefinitely.
Reliability as security (prevent abuse)
2xx fast-ack + async processing (avoid timeout retries)
Respond with a 2xx status quickly and process the payload asynchronously to avoid unnecessary retries.
Idempotency / dedupe guard
Implement idempotency to prevent duplicate processing from retries.
Mini incident: A team once processed duplicate orders due to missing idempotency, leading to customer refunds.
Endpoint hardening
Rate limits + body size limits
Apply rate limits (e.g., 60 requests per minute) and body size limits (e.g., 256KB) to prevent abuse.
Content-type enforcement + schema validation
Enforce JSON content-type and validate the payload schema to reject malformed requests.
IP allowlists (optional) + WAF
Optionally restrict to known IP ranges and use a Web Application Firewall for additional protection.
Micro checklist:
- Set rate limits based on expected traffic.
- Validate payload against a schema.
- Monitor for unusual IP addresses.
Operational controls
Secret storage and rotation
Store secrets in environment variables and rotate them regularly. See /docs/authentication/ — Required ingestion headers and token best practices for recommended token handling and rotation patterns.
Safe logging + correlation IDs
Log requests without exposing secrets, and use correlation IDs for tracing.
DLQ + replay procedures
Implement a Dead Letter Queue for failed messages and procedures to replay them safely.
Learn more about DLQ and replay.
Suggested diagram: A flowchart showing the webhook processing pipeline with security checks.
Go-live checklist
Local testing → staging → prod parity
Test locally, then in staging, ensuring parity with production.
Monitoring + alert thresholds
Set up monitoring for failures and alerts when thresholds are exceeded.
Minimal test snippet:
1 2 3 4 5curl -i -X POST "http://localhost:8000/webhooks/sendpromptly" \ -H "Content-Type: application/json" \ -H "X-SP-Timestamp: $TS" \ -H "X-SP-Signature: $SIG" \ --data "$BODY"
Use Sample Project to send one event and confirm your webhook passes signature checks.
Common failure modes
- Missing/incorrect signature validation → spoofed payloads. ([sendpromptly.com][1])
- No replay protection → attacker replays captured requests.
- No rate limiting → resource exhaustion.
- No dedupe → retries cause duplicate side effects.
- Logging secrets/tokens → credential leakage.
- No DLQ → you can’t recover poison events safely.
Learn more about signature mismatch troubleshooting.
Conclusion
Open Message Log to confirm: 2xx success, no repeats, and clear failure reasons when you force errors.
Key takeaways
- Verify signatures using raw body and constant-time comparisons.
- Enforce timestamp windows for replay protection.
- Implement rate limits and idempotency to prevent abuse.
- Use safe logging and correlation IDs for auditing.
- Test thoroughly before going live and monitor continuously.