Exclude: home-page and user signin/signup limit checks for un-authenticated users
What does this MR do and why?
Logged-out visitors from an IP that has used up its unauthenticated_traffic_per_ip allowance get a 429 on the home page (/). That blocks the usual way to sign in and sign up. A sign-in exclusion already exists, but users can't reach it from the home page. Several steps of the sign-in, sign-up, and account recovery journeys are also still counted, so a user can be blocked partway through.
There is a followup issue that prevents endpoint-abuse: gitlab-com/gl-infra/production-engineering#30240
This MR adds these routes to the unauthenticated_traffic_per_ip exclusion list in ee/lib/ee/gitlab/rate_limit/plan_rules.rb. The regexes are in ee/lib/ee/gitlab/path_regex.rb.
- Home page (
home_page_route_regex):/only./o/<organization_path>stays counted. - Sign-in steps (added to
sign_in_flow_route_regex_for):/users/sign_in_path(username lookup for two-step sign-in)/users/passkeys/sign_in/users/resend_verification_code/users/fallback_to_email_otp/users/skip_verification_for_now/users/skip_verification_confirmation/users/successful_verification
- Sign-up flow (
sign_up_flow_route_regex):/users(sign-up submit)/users/sign_up/users/password/complexity/users/:username/exists/users/almost_there/users/identity_verificationand its actions listed inee/config/routes/identity_verification.rb/-/subscriptions/payment_formand/-/subscriptions/validate_payment_method(credit card step of identity verification)/-/invites/:id(invite link that leads to sign-up)/-/arkose/data_exchange_payload
- Account recovery (
account_recovery_route_regex):/users/password(/new|/edit),/users/confirmation(/new), and/users/unlock(/new). - Trial registration (
trial_registration_route_regex):/-/trial_registrations(/new).
Except for the home page, these routes are also excluded under an /o/<organization_path> prefix.
Design choices
- The unauthenticated rules don't match on HTTP method, so each excluded path is excluded for every method. This includes the POSTs that submit sign-up, password reset, confirmation, unlock, and trial registration. A rule pair split by method would be needed to exclude only GETs.
- Each regex lists exact paths. The identity verification actions are listed explicitly, and a spec checks that every route of
Users::RegistrationsIdentityVerificationControlleris covered, so a new action fails the spec instead of silently staying counted. - The username check uses the browser's pattern, which allows
.gitand.atomendings, so every check the form sends is covered. /-/subscriptionsexcludes only the two actions that identity verification calls.SubscriptionsControlleralready allows them for anonymous users only during identity verification./-/invites/:idexcludes only the invite page.acceptanddeclinestay counted.POST /users(sign-up submit) keeps its own protections: the CSRF token, Arkose (or reCAPTCHA when Arkose is off),limit_signups_by_ip(20 per minute per IP), the sign-up enabled setting, email domain allow and deny lists, and identity verification before the new account can be used. Trial registration goes through the same controller checks. Identity verification actions keep their own send and attempt limits.- Accepted risk:
POST /users/unlock(resend unlock email) has no CAPTCHA or controller rate limit. It keeps the CSRF token check, and if/usersis in the instance's protected paths (the default) it is limited to 10 requests per minute per IP by prefix match. Devise only sends an unlock email for an account that is currently locked, and locked accounts also unlock after a timeout. A follow-up can add a dedicated limit if abuse shows up. - Signed-in users are unaffected. A spec confirms
GET /still counts againstburst_web_traffic_per_user_free_plan_log.
Not covered
- The countries query that the phone number input sends to
POST /api/graphql. Excluding/api/graphqlby path would exclude all GraphQL traffic, so this needs a separate change.
References
- Closes gitlab-com/gl-infra/production-engineering#30223
- Part of the epic Rate Limits · Platform & framework delivery
- Choosing a rate limiter
Screenshots or screen recordings
Not applicable. There are no UI changes.
How to set up and validate locally
- From an IP that has used up
unauthenticated_traffic_per_ip, check that these no longer return 429:/,/users/sign_in,/users/sign_up,/users/almost_there,/users/password/new,/-/trial_registrations/new. - Check that other anonymous routes still return 429, for example an issue page,
/o/<organization_path>, and/-/subscriptions/new. - While signed in, check that
GET /still counts against the signed-in user's limit.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.