Skip to content
Moosewave
Security & engineering

Email webhook security: verify the event before it changes the record

Review email webhook signatures, expected source context, safe certificate retrieval, durable intake, and replay-aware processing.

Moosewave6 min read
A sealed pink envelope passes through a blue keyhole gate beside a yellow inspection lens.

The short answer

An email webhook should earn the right to influence your records before its payload is trusted. Verify the provider’s documented signature and the expected source context, then persist a bounded event for replay-aware processing. A plausible bounce or delivery JSON document is not evidence of who sent it.

This guide uses Amazon SNS as a concrete verification example and a hypothetical delivery-event service for the processing design. Other providers use different signing schemes. It is not a copy-ready generic verifier, and a valid signature alone does not establish freshness, correct tenant routing, or the final current state of a subscriber.

  1. Implement the actual provider’s verification protocol.
  2. Check expected topic, account, region, and workspace routing where applicable.
  3. Do not fetch an arbitrary certificate URL from an untrusted payload.
  4. Separate durable intake from later state decisions.

1. Keep verification specific to the provider

Some webhook schemes sign exact body bytes; SNS uses a documented message-type-dependent string to verify. Do not apply a raw-body recipe to every provider or serialize parsed JSON and assume the signature will still match. Choose maintained verification tooling where available, then test it against the documented message types and signature versions used by your source.

Record the ingress contract: permitted message types, body limit, expected origin context, signing scheme, and failure behavior. Include subscription-control messages if your service receives them. A generic handler that understands only the delivery notification may accidentally treat another message type as a trusted business event. The boundary should explain what was verified, rather than returning one broad ‘trusted’ flag that downstream code interprets more generously than the verifier intended.

Reference: AWS: Verify SNS message signatures

2. Authenticate the event and constrain where it belongs

For SNS, check the expected TopicArn rather than accepting any correctly signed SNS notification. Resolve the account and workspace context from trusted configuration, not merely from a tenant identifier supplied inside the business payload. A legitimate notification for another environment should not mutate your production records. Keep staging and production source mappings explicit.

In our hypothetical service, two workspaces can each have a provider message identifier. The authenticated source mapping tells the processor which namespace that identifier belongs to. Do not join by an email address alone or allow a payload’s convenient workspace field to choose its own authority. Review how old provider integrations are retired so a once-approved source does not remain a permanent route into a workspace that no longer uses it.

3. Treat certificate retrieval as another security boundary

A SigningCertURL is still an input until it has been validated against the provider’s expected certificate origin and retrieval rules. Require HTTPS and tightly constrain the permitted host and path according to the supported scheme. A hostname substring test is not a safe substitute for URL parsing and an exact allowlist. Do not follow a redirect into an unrelated service or a private network destination.

Apply request timeouts, response-size limits, and bounded certificate caching appropriate to the verifier. Validate trust as the provider specifies instead of treating any returned certificate as authoritative. Avoid logging complete untrusted URLs that may carry unexpected data. A test should include an attacker-controlled certificate location and a misleading hostname. The purpose is not to become a general-purpose fetch service while trying to verify a small inbound event.

Reference: OWASP: SSRF Prevention

4. Acknowledge the event after safe intake, not after wishful processing

After verification and input validation, store the bounded event durably with its authenticated source, provider event identifier, receipt time, and schema context. Decide when the provider acknowledgement is appropriate according to your endpoint contract. If the durable write fails, do not claim successful intake just because parsing worked. Conversely, a slow downstream projection should not require repeatedly re-running every external verification step without a clear processing design.

Keep event identity and processing identity separate. A repeated notification should not repeatedly count as a new delivered recipient or trigger a fresh follow-up. Preserve the original observation, the attempt history, and the projection decision. Events can arrive out of order, so a later-received ‘accepted’ notification should not erase an already known terminal failure merely because its HTTP request completed later. Signature validity and current business state answer different questions.

5. Test invalid events alongside valid retries

Build fixtures for altered signatures, unsupported versions, unexpected topics, oversized bodies, invalid source mappings, duplicate identifiers, and reordered events. Include a legitimate repeated notification so the security boundary does not reject normal provider retries as an attack without a documented reason. Use the exact provider scheme when evaluating fixtures; a made-up test signer proves only that your made-up test path agrees with itself.

Inspect what is persisted and logged for each failure. A rejected body should not become a permanent collection of customer content in an error log. Use bounded reason codes and safe identifiers. Make certificate fetches observable enough to diagnose availability without exposing arbitrary payloads. An operator should be able to distinguish authentication failure, source mismatch, intake failure, and delayed projection, because each requires a different next action.

  • Provider-specific signature verification precedes business mutation.
  • Expected source context controls workspace routing.
  • Certificate fetches cannot choose arbitrary network destinations.
  • Acknowledgement follows the defined durable-intake boundary.
  • Duplicates and event ordering do not fabricate new outcomes.

6. Give the boundary a maintenance owner

Provider signing changes, certificate lifecycles, new regions, and account migrations can affect verification. Assign an owner to the ingress contract and keep fixtures versioned with the implementation. Alert on sustained verification or intake failures using coarse operational evidence, then investigate before loosening checks. Turning verification off to clear a backlog exchanges a visible outage for an untrusted mutation path.

A Moosewave template can help explain a verified incident or follow-up to the affected audience, but the webhook receiver is a separate security-sensitive system. An agent can summarize reason codes and prepare a bounded recovery plan without reading raw customer payloads or editing the allowlist automatically. Keep verified intake, interpretation, and any later outbound action as distinct stages with distinct authority. That separation makes both normal retries and security investigations easier to reason about.

Frequently asked questions

Direct answers to the questions that matter before this change reaches real recipients.
Does a valid provider signature prove the event is for my workspace?

No. Verify expected source context and route the event using trusted configuration. A valid event from another topic or environment should not mutate this workspace.

Can the handler download whatever SigningCertURL contains?

No. Validate the provider-specific certificate origin and constrain retrieval. Untrusted certificate fetching can create a separate server-side request forgery risk.

Should a duplicate event be rejected as malicious?

Not automatically. Providers can retry legitimate events. Authenticate each accepted request and use durable event identity so repetition does not repeat a business effect.

Primary sources checked for this guide

Sources checked 13 October 2026. Product behavior and documentation can change, so the linked primary source takes precedence if it differs from this article.

Share this article

From field note to next move

Turn the question into a reviewable plan.

Give Moosewave the outcome you want. The goal carries into a guided workspace with its scope, approval points, and evidence still attached.

Journal handoffGuided workspace · no live actions
Enter to preview · Shift + Enter for a new line

Opens a guided workspace. Nothing is sent or changed.

  1. 01UnderstandQuestion and evidence
  2. 02PlanScope and exclusions
  3. 03ApproveExact proposed action
  4. 04VerifyResult and receipt
From an operational question to a reviewed message

Make the message clear. Keep its operating contract intact.

Choose a Moosewave template, adapt the words to the reader’s task, and use these checks to review the sending and destination systems around it.