AI agents that react to external events via webhooks face a higher risk profile than traditional backend services. A corrupted database row is a fixable bug, but a webhook triggering an agent to send an email or update a customer record creates a real-world consequence that is difficult to reverse. The DEV.to article by Corsair Dev highlights that without strict verification, agents can act on replayed or forged requests, leading to duplicate actions or unauthorized state changes.
The Raw Body Problem in Signature Verification
Standard HMAC SHA256 verification often fails because modern frameworks like Express parse the incoming JSON body before the handler runs. If developers re-serialize the parsed object to verify the signature, whitespace and key ordering differences cause the hash to mismatch the provider’s original bytes. The solution requires capturing the raw request body before parsing, using methods like req.rawBody = buf in Express middleware. This ensures the signature check compares identical byte sequences, preventing false negatives on valid requests.
Blocking Replay Attacks with Timestamps
A valid signature only proves a request originated from the provider, not that it is fresh. Attackers can intercept signed payloads and resend them later, causing agents to repeat actions. To mitigate this, servers must validate a timestamp header, such as X-Slack-Request-Timestamp, within a tight 5-minute window. Crucially, the timestamp must be included in the string hashed by the provider; if an attacker modifies the header alone, the signature check will fail because the hashed content no longer matches.
Idempotency Keys Prevent Duplicate Agent Actions
Webhook providers guarantee 'at least once' delivery, meaning network blips often result in duplicate events. For agents, this can mean sending the same instruction twice. Developers must implement idempotency keys using the provider’s unique event or delivery ID. These keys should be stored with a unique constraint and a processing status. If an event arrives with a key that already exists, the agent should skip the action but return a success status to prevent further retries. A 24 to 72-hour retention window for these keys is recommended to cover typical retry periods.
Key Takeaways
- Always verify signatures using the raw, unparsed request body to avoid serialization mismatches.
- Incorporate timestamps into the hashed string to prevent replay attacks on agent actions.
- Use idempotency keys scoped per tenant to deduplicate events and prevent repeated real-world actions.
- Return 2xx immediately after verification and enqueue processing to avoid provider timeouts.
- Fall back to polling for historical backfill and reconciliation, as webhooks do not guarantee complete event history.
The Bottom Line
Treat webhook-triggered agent actions as irreversible transactions, not just data updates; if you aren't verifying raw bodies and enforcing idempotency, you're just automating chaos.