Harden SES webhook: allowlist SNS TopicArn after signature verification
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 39.9k
- Forks
- 3.4k
- Avg merge
- 6h 51m
- Merged PRs (30d)
- 232
Description
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 innodejs/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_arnoutput of theses-eventsTerraform 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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in nodejs/src/cdp/services/messaging/helpers/ses.ts and trace the SES webhook flow from signature verification through auto-confirmation and notification handling. Then inspect the charts configuration and the ses-events Terraform module's sns_topic_arn output; done means the allowlist is parsed and enforced in the stated order, warns while empty, and is wired per environment.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, node.js, terraform
- Domain
- backend, cloud, infrastructure, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100