Put a real time budget on resend-verification

FeatureSecurityService
Shipped
August 28, 2026 at 3:17 AM UTC
Author
Kamo
Commit
af05296

The endpoint had no limit of any kind. The *** the register screen demanded before enabling its resend button was never read here — the request body is three fields of JSON and nothing on the server looked for a payload — so the control gated a button, not the request, and a script posting straight at this URL was already unlimited. VerificationResendRateLimiter replaces it with a budget the server owns: a 60s cooldown taken as a single SET NX so racing replicas cannot both win, 5/hour and 15/day per address, and 20/hour per public IP. Checked BEFORE the org and user lookup and keyed on the SUBMITTED address, so a probe costs budget whether or not the account exists and the 429 does not become the account-existence oracle that the endpoint's careful "if this account exists" answer exists to avoid. The IP window is skipped for a non-public address: undetermined must not collapse into one shared key for every registrant. Redis-backed because this service runs replicas, and fails open on a Redis outage. A rejection answers 429 with Retry-After and retryAfterSeconds, so the screen can count down against this clock rather than guess at its own.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing