Items 1 and 2 merged to main via tenant-iso-mail (Fable review plus one re-check, CI green). Item 3, the shared SES reputation, stays open. The cheap option the fix agent found: SES tenants, with ses:TenantName enforced in the IAM policy, so each send names its tenant and a bad tenant is paused on its own.
Mail: a member can adopt another party's verified SES domain; sending-domain claims never expire Issue open
On branch tenant-iso-mail
Claimed by claude~paul@keymail.dev 3 weeks ago
Found by the 2026-10-03 tenant-isolation audit of main 78fc8d40, by reading code.
- High: a member can take over a sending domain already verified in SES outside CARLOS. -
POST .../email/domains(console/apimail.go:1016) is a member verb. It callsmail.EnsureDomainโclaimDomain, which is first-come (mail/domainclaim.go:119) โEnsureIdentity. - OnAlreadyExists,EnsureIdentityadopts the identity and its DKIM tokens (mail/aws.go:306-317) and overwrites MAIL FROM (:330). - Examples of exposed identities: tito.io (spec 2026-09-15 ยง1), the operator's own sign-in mail domain, and anything verified before the claim gate. -VerifyDomainreads Verified at once, so A's IAM policy then allows sending From*@thatdomain. It also rebinds the identity's configuration set to A's, and A's later Teardown deletes the identity, which breaks the real owner's mail. - Sending-domain claims never expire and need no proof (
mail/domainclaim.go:119-141,console/apimail.go:994-1031). Any account Admin can claimvictim.comand block every other tenant from it forever, and the refusal "already claimed by another CARLOS account" confirms someone holds it. - All tenants share one SES sending reputation. A credential cannot be forced to name a configuration set, and caps and pauses act on events after the fact. One abusive tenant risks an account-level SES suspension that stops mail for everyone.
Fixes for 1 and 2 are going on a branch from this session. 3 needs a design decision (a dedicated SES account per tenant, or enforcing the configuration set on every send), so it stays open here.
Tracked under #247 (tenant isolation before Carloku takes outside tenants).