🛡️ CVE-2026-54659 — pagy

⚪ Unknown ✅ No Known Exploit CWE-200 NVD
N/A
CVSS Score
0 Low4 Medium7 High9 Critical10

Description

Pagy I18n locale option is not validated before being used in a file path

Summary

Pagy::I18n.locale= did not validate its argument before using it as a

path component to load the matching dictionary file (<locale>.yml). An

application that assigns untrusted input to the locale — e.g. the common

pattern Pagy::I18n.locale = params[:locale] — let that input influence

which file Pagy attempted to load.

Details

The setter stored the value as-is, and the loader joined it into a path

and read it:

```ruby

# gem/lib/pagy/modules/i18n/i18n.rb

def locale=(value)

Thread.current[:pagy_locale] = value.to_s

end

# ...later, when translating:

path = pathnames.reverse.map { |p| p.join("#{locale}.yml") }.find(&:exist?)

dictionary = YAML.load_file(path)[locale]

```

Because the locale was used verbatim, a value such as an absolute path or

a ../-style string redirected the lookup outside the locales directory.

Pagy's subsequent structural check (dictionary['pagy']['p11n'])

prevents the file's contents from being returned, so this is not a

direct file read.

Fixed in 43.5.6 by constraining the locale to a BCP 47 shape before use:

```ruby

LOCALE_PATTERN = /\A[a-zA-Z]{2,8}(-[a-zA-Z0-9]{1,8})*\z/

def locale=(value)

Thread.current[:pagy_locale] = value.to_s[LOCALE_PATTERN]

end

```

Any non-matching value (including nil) resolves to the default locale

and never reaches the file lookup.

PoC

In an application that sets Pagy::I18n.locale = params[:locale], the

loader appends .yml and reads <locale>.yml, so the request param

controls the target path. For example, pointing it at the app's

config/database.yml:

1. Send a request with ?locale=../../../config/database (adjust the

number of ../ to reach the app root from the gem's locales/

directory).

2. Pagy calls YAML.load_file on the resulting …/config/database.yml.

3. The outcome differs by whether that .yml exists, is readable, parses

as YAML, and has Pagy's expected structure — an existing, readable

config/database.yml raises a different error than a non-existent

path (which silently falls back to the default locale). This yields a

file-existence / readability oracle for .yml paths, and the targeted

file is read into the process during the attempt.

Impact

Information disclosure (CWE-22 / CWE-200): a file-existence / readability

oracle for .yml paths on the host, plus a server-side read of

attacker-chosen files into the process. The file contents are not

returned in the response.

Only applications that pass unsanitized end-user input into

Pagy::I18n.locale= are affected. Applications that set the locale from

trusted values are not affected.

Patched: pagy 43.5.6.

Workaround (if you cannot upgrade): validate the locale before

assigning it, e.g.

Pagy::I18n.locale = params[:locale].to_s[/\A[a-zA-Z]{2,8}(-[a-zA-Z0-9]{1,8})*\z/],

or restrict it to your known set of locales.

How this vulnerability can be exploited

This issue can be reached over the network, attack complexity is low, an attacker needs no privileges on the target. No user interaction is required. Rated impact: confidentiality low, integrity none, availability none.

Weakness class

CVE-2026-54659 is classified as CWE-200: Exposure of Sensitive Information. Information that should stay internal is disclosed to someone who is not authorised to see it.

Affected software

CVE-2026-54659 is recorded against 2 packages.

  • pagy (from 43.0.0 up to 43.5.6)
  • unknown

Timeline and source

Published on 28 July 2026. No public exploit is currently recorded for this entry. Record sourced from NVD.

References

github.com (Web)
github.com (Web)
github.com (Web)
github.com (Package)
github.com (Web)

Details

Severity Unknown
CVSS Score N/A
CVSS Vector CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N
CWE CWE-200
Public Exploit ✅ No
Source NVD
Published 2026-07-28
Updated 2026-08-12
Modified 2026-07-28
Fix URL N/A

Affected Packages

Software From version Fixed in
pagy 43.0.0 43.5.6
unknown

Free Vulnerability Check

Is your site affected by CVE-2026-54659?

BotEraser helps you identify potentially vulnerable plugins and themes by checking your installation against CVE-2026-54659 and other known CVE records.

Scan My Site Free →

No credit card required  ·  Results in minutes

ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.