CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-54659

CVE-2026-54659: Directory Traversal and File Existence Oracle in Pagy I18n module

Alon Barad
Alon Barad
Software Engineer

Jul 29, 2026·6 min read·2 visits

Executive Summary (TL;DR)

A path traversal flaw in Pagy's I18n locale setter enables unauthenticated remote attackers to determine the existence and validity of YAML configuration files on the host filesystem via a side-channel oracle.

Pagy, an agile pagination gem for plain Ruby, contains a directory traversal vulnerability in its internationalization (I18n) module prior to version 43.5.6. An unauthenticated remote attacker can exploit this flaw by submitting path traversal sequences to the locale setter, allowing them to probe the server filesystem. The resulting behavior creates a highly reliable file existence and readability side-channel oracle for YAML files.

Vulnerability Overview

The affected component is the internationalization (I18n) module of Pagy, a widely used, lightweight pagination gem for the Ruby programming language. The security boundary is breached within the Pagy::I18n.locale= setter, which manages localization lookup tables. Because this setter handles locale assignments globally or thread-locally, applications that pass untrusted user input directly to it expose a critical file system interaction point.

The vulnerability is classified under CWE-22 (Improper Limitation of a Pathname to a Restricted Directory / 'Path Traversal') and CWE-200 (Exposure of Sensitive Information to an Unauthorized Actor). When exploited, this weakness permits an attacker to escape the intended directory constraint and probe the server filesystem. The attack surface is typically exposed through query parameters or HTTP request headers that configure user language preferences.

Although Pagy enforces structural schema validation on parsed files—which prevents direct retrieval of raw file contents—the application's response variations create a highly reliable file existence and readability oracle. This channel allows attackers to map the existence of configuration files, database configuration files, or other system YAML documents.

Root Cause Analysis

The root cause of CVE-2026-54659 is the total absence of input validation or sanitization within the Pagy::I18n.locale= setter method. In vulnerable versions, this method accepts any arbitrary string and writes it directly to the thread-local storage key :pagy_locale.

During translation lookups, the library constructs a file path by appending the user-controlled locale string directly to the localized file directory path. This string interpolation uses a standard file path resolution mechanism, ROOT.join('locales', "#{locale}.yml"). When the input contains path traversal sequences like ../ or absolute path directives, Ruby's Pathname#join resolves the sequence relative to the system root, allowing the path to escape the intended locales directory.

The application subsequently attempts to load the constructed path using the standard Ruby YAML library, specifically YAML.load_file(path). If an application is configured to pass raw user input (such as params[:locale]) directly to the Pagy setter, an attacker can influence the file system path supplied to the parser. The parser then attempts to load any YAML file on the local file system that matches the manipulated path.

Code Analysis & Patch Inspection

To understand the exact mechanics of the vulnerability and its remediation, we must examine the implementation within gem/lib/pagy/modules/i18n/i18n.rb. The vulnerable implementation accepted any string input, converting it directly using to_s and writing it to the thread-local storage context.

# Vulnerable code in gem/lib/pagy/modules/i18n/i18n.rb
def locale=(value)
  Thread.current[:pagy_locale] = value.to_s
end

The corrective patch, introduced in version 43.5.6, implements a strict validation system. The patch introduces a regular expression constant LOCALE_PATTERN conforming to BCP 47/RFC 4647 language tag standards. The setter now uses Ruby's String#[] syntax to slice the string, returning the string if it matches the pattern or nil if it fails validation.

# Patched code in gem/lib/pagy/modules/i18n/i18n.rb
module I18n
  class KeyError < KeyError; end
 
  # Regular expression validating only compliant BCP 47 language tags
  LOCALE_PATTERN = /\A[a-zA-Z]{2,8}(-[a-zA-Z0-9]{1,8})*\z/
 
  extend self
 
  # Assigns a validated locale to the current thread
  def locale=(value)
    Thread.current[:pagy_locale] = value.to_s[LOCALE_PATTERN]
  end
end

This validation pattern restricts acceptable input to letters and hyphens, strictly bound by the start-of-string (\A) and end-of-string (\z) anchors. This prevents multiline bypass attempts and completely blocks traversal characters like / or .. If an attacker attempts to inject a path traversal sequence, the pattern match fails, returning nil. This causes Pagy to fall back safely to the default locale configuration without executing file operations.

Exploitation & Side-Channel Oracle Mechanics

An attacker exploits this vulnerability by manipulating the parameter mapped to Pagy::I18n.locale. For example, an HTTP request to GET /items?locale=../../../../config/database causes the application to construct the file path /path/to/app/gem/locales/../../../../config/database.yml. Because Ruby resolves relative path traversals, the engine attempts to parse /path/to/app/config/database.yml.

The exploitation payload relies on side-channel analysis of application errors. If the targeted file does not exist, the framework handles the missing file error internally and falls back to the default locale, resulting in a normal HTTP 200 response. If the target file exists and is a valid YAML configuration, the load succeeds but fails to find the required Pagy localization schema, raising a Pagy::I18n::KeyError and causing an HTTP 500 response.

If the file exists but contains invalid YAML formatting, the Ruby interpreter raises a parsing exception such as Psych::SyntaxError, returning a distinct HTTP 500 error or stack trace. By correlating these application behaviors, an attacker can map file structures, confirm the existence of configuration directories, and locate critical database or credentials files.

Secondary Vector: Cross-Site Scripting in dev_tools

A secondary, parallel vulnerability was resolved alongside the path traversal issue within GitHub PR #908. This vulnerability occurs in Pagy's development tool helper (dev_tools), located in gem/lib/pagy/modules/abilities/configurable.rb. The component failed to sanitize or validate the wand_scale parameter, creating an injection vector when exposed to user-controlled values.

# Vulnerable implementation in configurable.rb
def dev_tools(wand_scale: 1)
  <<~HTML
    <script id="pagy-wand" data-scale="#{wand_scale}">
      #{ROOT.join('javascripts/wand.js').read}
    </script>
  HTML
end

If an application exposed this helper parameter directly to query inputs (e.g., Pagy.dev_tools(wand_scale: params[:scale])), an attacker could pass a string containing HTML escape characters. A payload such as 1"></script><script>alert(document.cookie)</script> would successfully break out of the script tag attribute and execute arbitrary JavaScript in the context of the user's browser session.

# Patched implementation in configurable.rb
def dev_tools(wand_scale: 1)
  <<~HTML
    <script id="pagy-wand" data-scale="#{wand_scale.to_f}">
      #{ROOT.join('javascripts/wand.js').read}
    </script>
  HTML
end

The remediation forces numeric type conversion by appending .to_f to the interpolated variable. When Ruby parses a string containing mixed malicious characters using .to_f, it truncates the input at the first non-numeric character. This turns the injection string into a harmless float value (e.g., 1.0), eliminating the cross-site scripting vector entirely.

Impact & Risk Assessment

The primary security impact of CVE-2026-54659 is localized information disclosure and filesystem reconnaissance. An unauthenticated remote attacker can probe the host filesystem to verify the presence of critical system files, framework configurations, and environment-specific database files. This provides the necessary intelligence to construct targeted secondary attacks.

The CVSS v4.0 base score is calculated at 6.9, reflecting a medium-severity profile. The metric string is 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. This indicates that while the vulnerability is remotely exploitable without authentication (AV:N/PR:N/UI:N), the impact is confined to low confidentiality loss (VC:L) without administrative modification capabilities or direct system compromise.

In combination with the secondary XSS vector in dev_tools, the overall exposure of unpatched installations is elevated in non-production or development-enabled environments. Developers must recognize that even though raw file content read capabilities are limited by schema validation checks, file existence oracles provide crucial telemetry to attackers mapping application environments.

Official Patches

ddnexusFix locale traversal path and wand_scale injection in dev_tools
ddnexusClean parameters before assigning PR
ddnexusPagy version 43.5.6 release notes
ddnexusOfficial Security Advisory

Fix Analysis (1)

Technical Appendix

CVSS Score
6.9/ 10
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

Affected Systems

Pagy pagination Ruby gem

Affected Versions Detail

Product
Affected Versions
Fixed Version
pagy
ddnexus
>= 43.0.0, < 43.5.643.5.6
AttributeDetail
CWE IDCWE-22, CWE-200
Attack VectorNetwork (Unauthenticated)
CVSS v4.0 Score6.9 (Medium)
Exploit StatusProof of Concept / Patch Available
ImpactLocal File Existence Reconnaissance & XSS
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1083File and Directory Discovery
Discovery
T1005Data from Local System
Collection
T1552Unsecured Credentials
Credential Access
CWE-22
Improper Limitation of a Pathname to a Restricted Directory

Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

Vulnerability Timeline

Official patch fix committed and merged via PR #908
2026-06-08
GitHub Advisory GHSA-2xmw-f8j8-wfxc published
2026-07-28
NVD publication and CVE State transition to PUBLISHED
2026-07-28

References & Sources

  • [1]Fix Commit
  • [2]Pull Request #908
  • [3]Release Notes
  • [4]GitHub Security Advisory

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•21 minutes ago•CVE-2025-6120
5.3

CVE-2025-6120: Heap-Based Buffer Overflow in Assimp HL1MDLLoader read_meshes

CVE-2025-6120 is a critical memory corruption vulnerability in the Open Asset Import Library (Assimp) affecting versions up to and including 5.4.3. The flaw is located in the Half-Life 1 MDL file format loader, specifically within the read_meshes function in HL1MDLLoader.cpp. It arises due to a lack of verification checks on array, bone, skin, or vertex indices parsed directly from a binary stream, resulting in a heap-based buffer overflow or out-of-bounds memory access.

Alon Barad
Alon Barad
1 views•5 min read
•25 minutes ago•GHSA-6XX4-9WP6-65P7
6.5

GHSA-6XX4-9WP6-65P7: Arbitrary Local File Disclosure via UNIX Symlink Following in skilo

A local file disclosure vulnerability exists in the Rust-based package skilo. When copying files during skill installation, the application recursively traverses directories but dereferences symbolic links, resulting in unauthorized local file reading.

Amit Schendel
Amit Schendel
0 views•5 min read
•about 2 hours ago•CVE-2026-66064
5.3

CVE-2026-66064: Incorrect Authorization and ACL Bypass via Trailing Slash in goshs

CVE-2026-66064 is an access control list (ACL) and blocklist bypass vulnerability in the goshs file server prior to version 2.1.5. Due to an inconsistency between uncleaned raw URI path evaluation and normalized file access, remote unauthenticated attackers can retrieve protected files, including the configuration file containing password hashes, by appending a trailing slash to the requested path.

Amit Schendel
Amit Schendel
4 views•6 min read
•about 3 hours ago•CVE-2026-54719
7.5

CVE-2026-54719: Access Control List Authorization Bypass in goshs via bulk ZIP Download Route

CVE-2026-54719 is a high-severity Access Control List (ACL) authorization bypass vulnerability in goshs, a lightweight HTTPS-capable server used for file sharing. The issue allows unauthenticated network attackers to completely bypass file-level and directory-level authentication mechanisms and blocklists by requesting protected resources via the bulk ZIP-download route (?bulk). This vulnerability represents a residual flaw following a partial remediation attempt for CVE-2026-40189.

Alon Barad
Alon Barad
4 views•6 min read
•about 4 hours ago•CVE-2026-52888
6.8

CVE-2026-52888: Sensitive Data Exposure and Blacklist Bypass in NocoBase SQL Collection Plugin

NocoBase, an extensible low-code platform, was found to contain an information exposure vulnerability in its SQL Collection plugin. The validator designed to inspect SQL queries used an incomplete keyword-based blacklist, allowing users with administrative or collection creation privileges to bypass restrictions and execute arbitrary SELECT queries against PostgreSQL system catalogs. This flaw permits unauthenticated or privilege-escalated access to critical system files, active connection listings, and system user password hashes.

Alon Barad
Alon Barad
5 views•6 min read
•about 5 hours ago•CVE-2026-54603
8.6

CVE-2026-54603: Cross-Origin Credential Leakage and SSRF via Protocol-Relative Redirects in ruby-oauth2

An issue in the ruby-oauth2 gem allows unauthenticated attackers to steal OAuth access tokens or perform Server-Side Request Forgery (SSRF) via a protocol-relative URI in HTTP Location redirect headers.

Amit Schendel
Amit Schendel
3 views•7 min read