fix: verify SNS callback signatures
The SES callback currently trusts a matching TopicArn without authenticating the SNS message. A forged request that knows the topic ARN can reach event processing, and subscription confirmations can make the server follow an unverified URL.
This verifies the AWS SNS canonical signature before processing any message, restricts signing certificates and subscription URLs to the regional SNS host encoded by the topic ARN, rejects redirects and malformed messages, and removes the development-mode verification bypass. Valid SNS signature versions 1 and 2 remain supported.
Verification:
pnpm --filter=web exec vitest run -c vitest.unit.config.ts src/server/security/sns-message-validator.unit.test.ts src/app/api/ses_callback/route.unit.test.tspnpm test:web:unit(131 tests)pnpm --filter=web typecheck- focused ESLint on the changed files
Summary by cubic
Authenticate AWS SNS messages in the SES webhook. Previously we trusted any request with a matching TopicArn and followed subscription URLs; now we verify SNS canonical signatures (v1/v2), pin certificate and confirmation hosts to the TopicArn’s region, bound external calls (no redirects, 5s timeout), and only record success after a confirmed subscription.
- Removes the development-mode verification bypass; all requests must pass signature verification.
- Returns 400 for invalid JSON, 401 for unsigned/tampered or untrusted events, and 502 when subscription confirmation fails.
- Requires outbound HTTPS to https://sns..amazonaws.com (or .com.cn).
Summary by CodeRabbit
-
Security Enhancements
- Strengthened SNS notification validation and signature verification.
- Rejected malformed, unsigned, tampered, or incorrectly sourced events.
- Restricted certificate and subscription URL requests to trusted HTTPS endpoints.
- Prevented redirects and enforced timeouts when retrieving certificates or confirming subscriptions.
- Removed development-mode validation bypasses.
-
Bug Fixes
- Malformed request bodies now return a clear client error.
- Invalid notification events return an unauthorized response.
- Confirmation failures return an appropriate gateway error without recording success.