Skip to content

Harden SES webhook: allowlist SNS TopicArn after signature verification #61644

@dmarchuk

Description

@dmarchuk

Background

Follow-up from #60229 (email tracking code signing). The SES event webhook (/public/m/ses_webhook) verifies the SNS message signature, which proves the envelope was signed by some AWS SNS topic - but not that it came from our SES notification topic. The handler also auto-confirms any sns.<region>.amazonaws.com subscription.

Gap

An attacker can create their own SNS topic, get our endpoint to auto-confirm it, then publish a signed Bounce notification with a forged tracking tag - reaching recipientsManager.optOut for a team. A valid signature alone doesn't stop this.

This is pre-existing (not introduced by #60229). #60229 mitigates the main vector over time by signing tracking codes (once unsigned codes are rejected, a forged bounce needs a code that decodes to a valid team), but a residual recipient-replay vector remains, and the auto-confirm of foreign topics is itself undesirable.

Fix

After signature verification (and before auto-confirm / notification handling), reject envelopes whose TopicArn is not in an allowlist of our SES notification topic ARNs.

  • New config CDP_SES_WEBHOOK_ALLOWED_TOPIC_ARNS (comma-separated), parsed into a set in nodejs/src/cdp/services/messaging/helpers/ses.ts.
  • Empty default = allow-all (+ warn), so the code can ship before the env is configured; enforcement turns on once charts sets the var per env. No code redeploy needed to enable.
  • Wire the env per environment in charts to the sns_topic_arn output of the ses-events Terraform module (differs by region/account).

Related

  • Also track here: enforce signed tracking codes (reject unsigned) once existing in-flight unsigned links have aged out. That closes the broader forged-event surface.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions