What Is Webhook Security?
- Webhook security protects event-driven HTTP endpoints from forged, replayed, tampered, and abusive requests.
- Verify provider signatures against the raw request body, require TLS, validate payloads, and use idempotent handlers.
- Treat exposed webhook URLs as credentials and rotate them when leaked.
Definition#
Webhook security is the set of controls used to authenticate, authorize, validate, process, and monitor HTTP requests that deliver event notifications between systems. It prevents attackers from impersonating a trusted sender, modifying event data, replaying old requests, or abusing the receiving endpoint.
A secure webhook implementation verifies that a request came from the expected provider, confirms that the message has not been altered, limits what the handler can do, and safely handles retries and failures.
Analyst’s Take: Signature verification is necessary, but it is not sufficient. A valid request can still be replayed, carry unsafe input, or trigger excessive privileges, so the receiving application must enforce time limits, validate payloads, and constrain the handler’s permissions.
How It Works#
A webhook usually works as follows:
- A source system detects an event, such as a payment update, user change, deployment, or alert.
- The source sends an HTTP request, commonly a
POST, to a configured endpoint. - The receiving application authenticates and validates the request.
- The application queues or processes the event.
- The source retries delivery if it receives a timeout or an unsuccessful response.
Apply security controls at each stage.
Authenticate the Sender
The most common approach is a signed request. The provider and recipient share a secret. The provider calculates an HMAC over the request body, often combined with a timestamp, and sends the result in a header.
The recipient independently calculates the expected signature and compares it with the supplied value using a constant-time comparison. This prevents attackers from learning the correct signature through timing differences.
Use the raw request body for verification. Parsing JSON and serializing it again can change whitespace, ordering, escaping, or encoding and cause valid signatures to fail. Do not verify a signature over a reconstructed object unless the provider explicitly defines that behavior.
Static bearer tokens can also authenticate webhooks, but they provide less protection against tampering and replay unless combined with timestamps, expiration, or another control. Never place secrets in query strings, because URLs may be recorded in logs, browser history, proxies, and monitoring systems.
Store signing secrets in a suitable secrets manager rather than source code or ordinary configuration files. A password manager such as Try 1Password → may help smaller teams control access to integration credentials, but production applications should retrieve secrets through an application secrets-management system.
Prevent Replay Attacks
A valid signed request may still be dangerous if an attacker captures it and sends it again. Replay protection typically combines:
- A timestamp included in the signed data
- A narrow acceptance window, such as a few minutes
- A unique event ID or delivery ID
- A short-lived record of recently processed identifiers
Reject requests outside the accepted time window and record event identifiers before processing state-changing operations. Account for reasonable clock skew, but avoid accepting requests indefinitely.
Understanding the potential impact of compromised credentials is also useful when setting controls. See the FAQ on the blast radius of a credential for additional context.
Protect the Transport and Endpoint
Require HTTPS with a valid certificate. Redirecting HTTP to HTTPS is not a substitute for requiring HTTPS, because sensitive data may already have been sent before the redirect.
Where supported, mutual TLS can provide an additional client-authentication layer. Network controls such as provider IP allowlists can reduce exposure, but IP ranges can change and should not replace cryptographic verification.
Keep webhook endpoints separate from administrative interfaces. Apply rate limits, request-size limits, connection timeouts, and upstream filtering. Return responses promptly when possible by placing work on a queue rather than performing lengthy processing inside the request.
Validate and Contain the Payload
A valid signature confirms the message’s origin and integrity, not that every field is safe or appropriate. Validate the schema, data types, required fields, lengths, and allowed values. Treat all payload content as untrusted input.
Security testing should include the webhook’s authentication and input-validation paths. Dynamic testing concepts covered in DAST, or dynamic application security testing can help identify weaknesses in exposed handlers.
Avoid passing webhook fields directly into shell commands, SQL statements, file paths, templates, or authorization decisions. Use parameterized queries, output encoding, and allowlists where applicable.
The webhook handler should have only the permissions it needs. For example, a deployment notification should not have unrestricted database access, and a billing event processor should not be able to modify unrelated identity records.
Make Processing Idempotent
Providers commonly retry when delivery times out or returns an error. Your handler should produce the same safe result when it receives the same event more than once.
Use the provider’s event ID as an idempotency key. Store processing state in a durable data store and define how to handle events that arrive out of order. Acknowledge only after the event is durably accepted, or use a queue that provides the required delivery guarantees.
Monitor Delivery and Verification Failures
Log enough information to investigate failures without recording secrets or complete sensitive payloads. Useful fields include:
- Provider or integration name
- Event ID and event type
- Request timestamp
- Verification result
- Response status and processing duration
- Retry count
- Queue or handler outcome
Alert on unusual signature failures, spikes in request volume, repeated event IDs, unexpected event types, and sustained delivery errors. Rotate webhook secrets through a documented process and test the new secret before disabling the old one when dual-secret validation is supported.
When You’ll Encounter It#
You will encounter webhook security whenever an external or internal service sends event-driven HTTP requests to your application. Common examples include:
- Payment and subscription status notifications
- Source-control push, pull request, and release events
- CI/CD deployment triggers
- Identity and user-provisioning events
- Security alerts and monitoring notifications
- CRM, ticketing, and communication integrations
- Infrastructure automation and serverless triggers
- Internal microservice event delivery
The risk is highest when a webhook can trigger privileged actions, modify records, issue refunds, deploy code, create accounts, or invoke other automation. Publicly reachable endpoints also attract scanning and unsolicited traffic, even when the integration itself is low impact.
Related Terms
- HMAC: A keyed hash used to verify message integrity and authenticity when both parties share a secret.
- Signature verification: The process of calculating an expected signature and comparing it with the sender’s signature.
- Replay attack: Reuse of a previously valid request to repeat an action.
- Idempotency: Designing an operation so repeated delivery produces one safe outcome rather than duplicate effects.
- Event ID: A unique identifier used to track, deduplicate, and investigate webhook deliveries.
- Mutual TLS: TLS authentication in which both the server and client present certificates.
- Dead-letter queue: A queue for events that could not be processed after defined retry attempts.
- Webhook secret rotation: Replacing a signing secret while minimizing delivery interruptions.
- Least privilege: Granting the webhook handler only the permissions required for its function.
Technical Notes#
A generic HMAC verification flow should use the provider’s documented canonicalization and header format. The following pseudocode illustrates the security properties without assuming a specific vendor:
import hmac
import hashlib
import time
def verify_webhook(raw_body, supplied_signature, supplied_timestamp, secret):
now = int(time.time())
timestamp = int(supplied_timestamp)
# Reject stale or excessively future-dated requests.
if abs(now - timestamp) > 300:
return False
signed_value = f"{supplied_timestamp}.{raw_body}".encode()
expected = hmac.new(
secret.encode(),
signed_value,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, supplied_signature)
A request handler should also enforce transport and payload limits at the edge or application layer:
Require HTTPS: yes
Maximum body size: 1 MB
Request timeout: 10 seconds
Accepted methods: POST
Accepted content type: application/json
Replay window: 300 seconds
Test the integration with valid, altered, expired, duplicated, oversized, and malformed requests. Confirm that failed verification does not trigger business actions, that retries do not create duplicate effects, and that logs do not expose signing secrets or authorization headers.
Start with verification of the raw request body and a bounded replay window. Then confirm that the handler validates every field, runs with only the required permissions, and acknowledges work only after durable acceptance.
This article may contain affiliate links. We earn a commission on qualifying purchases at no extra cost to you.