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.
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 anysns.<region>.amazonaws.comsubscription.Gap
An attacker can create their own SNS topic, get our endpoint to auto-confirm it, then publish a signed
Bouncenotification with a forged tracking tag - reachingrecipientsManager.optOutfor 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
TopicArnis not in an allowlist of our SES notification topic ARNs.CDP_SES_WEBHOOK_ALLOWED_TOPIC_ARNS(comma-separated), parsed into a set innodejs/src/cdp/services/messaging/helpers/ses.ts.sns_topic_arnoutput of theses-eventsTerraform module (differs by region/account).Related