Designing a signup form that does not leak who is registered
18 July 2026 · 5 min read
Any difference in response between a known and unknown address is an oracle. Attackers use it to test lists against your service, and for some services simply being a member is sensitive.
Where the difference hides
- Different wording, obviously.
- Different status codes.
- Different response times, because one path hashes a password and the other does not.
- Different rate-limit thresholds, which leaks over several attempts.
The usual resolution
Answer identically and send an email that differs: "here is your account" or "someone tried to sign up with your address". The person who owns the mailbox learns the truth and nobody else does.
We use the same principle for aliases. A blocked alias, an unconfirmed one and one that never existed all answer with the same 550, byte for byte, because telling a spammer they are being blocked confirms a real person is behind the address.
More on for developers
Testing signup emails in CI without a real mailbox
Sleep-and-hope is why your email tests are flaky. Here is the shape that is not.
Webhook signatures, done properly
A shared secret in a header is not a signature. Here is what to send, what to check, and the two mistakes almost everyone makes on the receiving end.
Rate limiting on the wrong axis is worse than none
Per-IP limits punish shared offices and mobile networks while doing nothing to an attacker who rotates addresses for pennies.