Limit daily phone verification transactions per dial code

What does this MR do and why?

Limit daily phone verification transactions per dial code

SMS pumping attacks target a single destination, and the global limits trip too late for low-traffic countries. Require credit card verification once a dial code exceeds its daily SMS limit, behind a feature flag.

Related to https://gitlab.com/gitlab-org/gitlab/-/work_items/609536

References

Screenshots or screen recordings

How to set up and validate locally

The check runs before any Telesign call, so no Telesign credentials are needed.

Prerequisites

  • GDK running in SaaS mode (GITLAB_SIMULATE_SAAS=1).
  • Identity verification enabled: email confirmation set to hard, admin approval for sign-ups off, and both phone and credit card verification enabled (these are the defaults).

1. Enable the flag, set a low limit, and fill the counter

In gdk rails console:

Feature.enable(:limit_phone_verification_transactions_by_dial_code)
ApplicationSetting.current.update!(dial_code_phone_verification_transactions_daily_limit_overrides: { '44' => 2 })

key = :dial_code_phone_verification_transactions_limit
opts = { scope: { international_dial_code: 44 }, threshold: 2 }
3.times { Gitlab::ApplicationRateLimiter.throttled?(key, **opts) }
Gitlab::ApplicationRateLimiter.peek(key, **opts) # => true
Why 3 increments for a limit of 2

A send is counted after it goes out, and the limit trips once the count is above the limit. With a limit of 2, three sends go through and the fourth attempt is blocked.

Wait about a minute, or run gdk restart rails-web, so the web server picks up the flag and setting.

2. Create a user who gets a phone verification step

  1. Sign up a new user at /users/sign_up.

  2. Before verifying the email, give the user a Medium risk band so a phone step is required:

    UserCustomAttribute.upsert_custom_attribute(
      user_id: User.find_by(username: '<username>').id,
      key: UserCustomAttribute::ARKOSE_RISK_BAND,
      value: 'Medium'
    )
  3. Verify the email with the code from /rails/letter_opener.

3. Try to send a code to the over-limit dial code

On the phone step, enter any +44 number and send a code.

Expected

  • No SMS is sent, and the page reloads with credit card as the next step (email → credit card → phone).

  • log/application_json.log contains:

    {"message":"IdentityVerification::UserRiskProfile","event":"User assumed high risk.","reason":"Dial code phone verification daily transaction limit exceeded"}

Cleanup

Feature.disable(:limit_phone_verification_transactions_by_dial_code)
ApplicationSetting.current.update!(dial_code_phone_verification_transactions_daily_limit_overrides: {})

The +44 counter clears itself within 24 hours.

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.

Edited by Jay

Merge request reports

Loading
Loading