
PEACH
Un framework di isolamento del tenant
?set_locale= wrote the request's value into Avo.configuration.locale, a setting shared by every request the Ruby process serves. It did so before Avo's authenticate block ran.
?set_locale=zz) was stored, and every later Avo request from every user raised I18n::InvalidLocale (HTTP 500) until the process restarted.config.authenticate_with rather than a route constraint, both worked without signing in.Fixed in avo 4.3.1 and avo 3.33.1.
Avo 3 apps that use avo-pro or avo-advanced also need 3.33.1 of avo-pro, avo-advanced, avo-dashboards, avo-menu and avo-dynamic_filters, because they pin the avo version exactly. Run bundle update avo together with those gems.
Unknown locales in set_locale and force_locale are now ignored, and set_locale is stored only after the authenticate block lets the request through: avo-hq/avo#4886 and avo-hq/avo#4893 (4.x), avo-hq/avo#4894 (3.x).
authenticate :user do ... end), so signed-out requests never reach Avo's controllers. Signed-in users can still trigger the bug until you upgrade.Avo.configuration.locale mutation via params[:set_locale]Avo::BaseApplicationController#set_avo_locale is registered as an around_action and writes Avo.configuration.locale from params[:set_locale]:
# app/controllers/avo/base_application_controller.rb
around_action :set_avo_locale
...
def set_avo_locale(&action)
locale = Avo.configuration.default_locale
if params[:set_locale].present?
locale = params[:set_locale]
Avo.configuration.locale = locale # <-- mutates global config
end
I18n.with_locale(locale, &action)
endAvo.configuration is the application-wide singleton built in Avo::Configuration and reused across every request handled by the same Ruby process. Writing to Avo.configuration.locale therefore persists the value globally — it affects every other in-flight and future request, served to every other user, until the process is restarted or a subsequent request explicitly resets it.
A second issue is callback ordering: set_avo_locale is an around_action registered before _authenticate! in the BaseApplicationController callback chain, so the mutation happens before authentication. Whether it is reachable pre-auth depends on the host application's Avo.configuration.authenticate proc — anything that renders before redirecting (or any host that allows public access to a single avo URL such as a status / health endpoint) gives unauthenticated attackers a write primitive against Avo.configuration.locale.
All current 3.x releases up to 3.31.2 and the v4.0.0 betas are affected.
set_avo_locale around_action (i.e. anything inheriting BaseApplicationController — effectively the whole engine).authenticate proc lets the around_action complete before redirecting (the around_action runs to its first yield before _authenticate!'s before_action is invoked, so the mutation always lands).A reproducible RSpec request spec is provided at spec/requests/avo/locale_global_state_spec.rb:
it "persists the attacker-supplied locale on the global Avo.configuration" do
original = Avo.configuration.locale
get "/admin?set_locale=xx-poisoned"
expect(Avo.configuration.locale).to eq("xx-poisoned")
Avo.configuration.locale = original
endEnd-to-end with curl:
curl -b session.txt "https://target/admin?set_locale=xx-poisoned"
# every subsequent request served by the same Puma worker now starts
# with Avo.configuration.locale == "xx-poisoned" (until another set_locale
# overrides it or the worker restarts).Avo.configuration.locale (rather than per-request I18n.locale) return missing-translation strings or fall back unpredictably for every user.Avo.configuration.locale (e.g. for caching keys, log routing, default behavior) inherits the corruption automatically.params[:force_locale] (set_force_locale) and other I18n.with_locale paths can be used to force missing-translation behavior for other admins (denial-of-service of the UI for the attacker's chosen scope).
CVSS v3.1 estimate: 3.7 / Low — AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N. Higher if reachable pre-auth.Treat params[:set_locale] as request-local input, never write to Avo.configuration:
def set_avo_locale(&action)
locale = params[:set_locale].presence || Avo.configuration.default_locale
I18n.with_locale(locale, &action)
endIf a deployment legitimately needs to "remember" a user's locale across requests, that belongs in the user record or the session — not in a process-global singleton.
Optionally, restrict the value against I18n.available_locales so a malformed locale doesn't poison I18n.with_locale:
def set_avo_locale(&action)
requested = params[:set_locale].to_s
locale = if I18n.available_locales.map(&:to_s).include?(requested)
requested
else
Avo.configuration.default_locale
end
I18n.with_locale(locale, &action)
endA regression test is included with the PoC above.
Reported privately via GitHub Security Advisory.
Fonte: NVD
Valutazione gratuita delle vulnerabilità
Valuta le tue pratiche di sicurezza del cloud in 9 domini di sicurezza per stabilire un benchmark del tuo livello di rischio e identificare le lacune nelle tue difese.
Richiedi una demo personalizzata
"La migliore esperienza utente che abbia mai visto offre piena visibilità ai carichi di lavoro cloud."
"Wiz fornisce un unico pannello di controllo per vedere cosa sta succedendo nei nostri ambienti cloud."
"Sappiamo che se Wiz identifica qualcosa come critico, in realtà lo è."