Skip to content

Revert #7470 (default_url_options strip) -- exposes locale-leak regression#7476

Merged
ShanaLMoore merged 1 commit into
mainfrom
revert-7470-locale-leak
May 27, 2026
Merged

Revert #7470 (default_url_options strip) -- exposes locale-leak regression#7476
ShanaLMoore merged 1 commit into
mainfrom
revert-7470-locale-leak

Conversation

@ShanaLMoore

Copy link
Copy Markdown
Contributor

Summary

Reverts #7470. That PR (merged earlier today) changed Hyrax::Controller#default_url_options to only emit locale: when the active locale differs from I18n.default_locale. After deploy to koppie (https://pg.nurax.samvera.org), Hyrax began rendering pages in random non-default locales for users who had never requested those locales.

The regression is real and user-visible. The fix in #7470 is correct in concept but uncovered a latent cross-request I18n.locale leak in Hyrax that the previous always-append behavior was inadvertently masking. The leak deserves its own diagnosis and fix; this PR restores the pre-#7470 behavior so staging/production aren't degraded while that happens.

Reproduction (live on pg.nurax)

Six consecutive cookie-less, Accept-Language-less curls all return a sign-in form whose action carries a non-default locale:

for i in 1 2 3 4 5 6; do
  curl -s https://pg.nurax.samvera.org/users/sign_in \
    | grep -o 'action=\"/users/sign_in[^\"]*\"' | head -1
done

Output (during my session):

action=\"/users/sign_in?locale=it\"
action=\"/users/sign_in?locale=it\"
action=\"/users/sign_in?locale=it\"
action=\"/users/sign_in?locale=it\"
action=\"/users/sign_in?locale=it\"
action=\"/users/sign_in?locale=it\"

LaRita and I also saw it interactively: navigating from catalog search to the dashboard randomly flips the UI to Portuguese, French, Italian, German etc., even though the user only browses in English and never picked a non-English locale.

Why #7470's symptom is the leak being unmasked

Pre-#7470, default_url_options unconditionally merged locale: I18n.locale. Every link, redirect, and form action carried ?locale=X. Every subsequent request hit Hyrax::Controller#set_locale:

def set_locale
  I18n.locale = params[:locale] || I18n.default_locale
end

with a non-nil params[:locale], so I18n.locale got forcibly pinned to a known value at the start of every request. Any other code path that mutated I18n.locale or I18n.default_locale was effectively overwritten on the next request.

Post-#7470, default-locale users navigate URLs with no ?locale= param. set_locale falls through to I18n.default_locale. If anything in the request lifecycle is mutating I18n.locale (or I18n.default_locale) and the value persists across requests on the same Puma worker, the next visitor inherits that stale value. The deterministic per-worker stickiness in the curl repro above is consistent with this.

I have not yet identified the exact mutator. Candidates worth checking:

  • app/models/user_mailbox.rb -- uses I18n.t(..., locale: preferred_locale) (kwarg form should be safe but worth ruling out)
  • app/channels/hyrax/notifications_channel.rb -- writes current_user.update(preferred_locale: data['locale'])
  • app/controllers/concerns/hyrax/works_controller_behavior.rb -- has its own locale = params[:locale] || current_user&.preferred_locale || I18n.default_locale branch
  • presenters and renderers in app/presenters/ / app/renderers/ that read I18n.locale at URL-build time
  • anything setting I18n.default_locale = (vs I18n.locale =) anywhere in the boot/initializer path

Refs

Plan to re-land

  1. This revert merges and pg.nurax goes back to normal (random language flips stop).
  2. New issue filed for the I18n.locale cross-request leak with the curl repro.
  3. Once the leak is fixed (independent PR), re-open the equivalent of Strip default locale from default_url_options #7470 layered on top.
  4. Resume Bump hyrax to include #7470 (strip default locale from URLs) hyku#3071.

Test plan

  • CI green on this branch.
  • After merge + deploy to pg.nurax, the curl loop above returns 6 forms with action=\"/users/sign_in?locale=en\" (or other stable locale) instead of 6 differing locales.

🤖 Generated with Claude Code

…le-from-urls"

This reverts commit 7f0e346, reversing
changes made to f62afa4.
@ShanaLMoore

Copy link
Copy Markdown
Contributor Author

Filed #7477 with the cross-request locale-leak repro and candidates list. Once that lands, this revert can be reversed.

@github-actions

github-actions Bot commented May 26, 2026

Copy link
Copy Markdown

Test Results

    17 files  ±0      17 suites  ±0   3h 26m 6s ⏱️ - 7m 50s
 7 596 tests  - 2   7 290 ✅  - 2  306 💤 ±0  0 ❌ ±0 
25 710 runs   - 9  25 117 ✅  - 9  593 💤 ±0  0 ❌ ±0 

Results for commit ad72d6d. ± Comparison against base commit 7f0e346.

This pull request removes 449 and adds 447 tests. Note that renamed tests count towards both.
spec.abilities.ability_spec ‑ Hyrax::Ability AdminSets and PermissionTemplates a user without edit access is expected not to be able to create #<Hyrax::PermissionTemplate:0x00007efbc1ff0500>
spec.abilities.ability_spec ‑ Hyrax::Ability AdminSets and PermissionTemplates a user without edit access is expected not to be able to create #<Hyrax::PermissionTemplate:0x00007effda9b7a90>
spec.abilities.ability_spec ‑ Hyrax::Ability AdminSets and PermissionTemplates a user without edit access is expected not to be able to create #<Hyrax::PermissionTemplate:0x00007f3380eb7458>
spec.abilities.ability_spec ‑ Hyrax::Ability AdminSets and PermissionTemplates a user without edit access is expected not to be able to create #<Hyrax::PermissionTemplate:0x00007f70287a85d8>
spec.abilities.ability_spec ‑ Hyrax::Ability AdminSets and PermissionTemplates a user without edit access is expected not to be able to create #<Hyrax::PermissionTemplateAccess:0x00007efbc203ce50>
spec.abilities.ability_spec ‑ Hyrax::Ability AdminSets and PermissionTemplates a user without edit access is expected not to be able to create #<Hyrax::PermissionTemplateAccess:0x00007effda9c4380>
spec.abilities.ability_spec ‑ Hyrax::Ability AdminSets and PermissionTemplates a user without edit access is expected not to be able to create #<Hyrax::PermissionTemplateAccess:0x00007f3380ec4748>
spec.abilities.ability_spec ‑ Hyrax::Ability AdminSets and PermissionTemplates a user without edit access is expected not to be able to create #<Hyrax::PermissionTemplateAccess:0x00007f70280eeee0>
spec.abilities.ability_spec ‑ Hyrax::Ability AdminSets and PermissionTemplates a user without edit access is expected not to be able to destroy AdminSet: 25bb1271-90d3-4707-886d-aaa8dc98310d
spec.abilities.ability_spec ‑ Hyrax::Ability AdminSets and PermissionTemplates a user without edit access is expected not to be able to destroy Hyrax::AdministrativeSet: 212079b5-95b4-4560-9ec3-a13c35696b38
…
spec.abilities.ability_spec ‑ Hyrax::Ability AdminSets and PermissionTemplates a user without edit access is expected not to be able to create #<Hyrax::PermissionTemplate:0x00007efdc4ab7e58>
spec.abilities.ability_spec ‑ Hyrax::Ability AdminSets and PermissionTemplates a user without edit access is expected not to be able to create #<Hyrax::PermissionTemplate:0x00007f987abafa08>
spec.abilities.ability_spec ‑ Hyrax::Ability AdminSets and PermissionTemplates a user without edit access is expected not to be able to create #<Hyrax::PermissionTemplate:0x00007fab65f65780>
spec.abilities.ability_spec ‑ Hyrax::Ability AdminSets and PermissionTemplates a user without edit access is expected not to be able to create #<Hyrax::PermissionTemplate:0x00007fb27529d220>
spec.abilities.ability_spec ‑ Hyrax::Ability AdminSets and PermissionTemplates a user without edit access is expected not to be able to create #<Hyrax::PermissionTemplateAccess:0x00007efdc4ac5008>
spec.abilities.ability_spec ‑ Hyrax::Ability AdminSets and PermissionTemplates a user without edit access is expected not to be able to create #<Hyrax::PermissionTemplateAccess:0x00007f987abf2a88>
spec.abilities.ability_spec ‑ Hyrax::Ability AdminSets and PermissionTemplates a user without edit access is expected not to be able to create #<Hyrax::PermissionTemplateAccess:0x00007fab66102958>
spec.abilities.ability_spec ‑ Hyrax::Ability AdminSets and PermissionTemplates a user without edit access is expected not to be able to create #<Hyrax::PermissionTemplateAccess:0x00007fb2752a80d0>
spec.abilities.ability_spec ‑ Hyrax::Ability AdminSets and PermissionTemplates a user without edit access is expected not to be able to destroy AdminSet: 2d514e8d-de30-49d9-936b-695d4abdf4e9
spec.abilities.ability_spec ‑ Hyrax::Ability AdminSets and PermissionTemplates a user without edit access is expected not to be able to destroy Hyrax::AdministrativeSet: 9df6b795-967f-444e-bd77-48887b53125c
…

♻️ This comment has been updated with latest results.

@ShanaLMoore ShanaLMoore merged commit 4960b5e into main May 27, 2026
57 of 58 checks passed
@ShanaLMoore ShanaLMoore deleted the revert-7470-locale-leak branch May 27, 2026 13:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants