Dev.to Security 🔐 Cybersecurity 👁 0 📖 3 min read

CVE-2026-125110: CVE-2026-125110: Path Canonicalization Mismatch and Security Header Bypass in Rack::Static

CVE-2026-125110: Path Canonicalization Mismatch and Security Header Bypass in Rack::Static Vulnerability ID: CVE-2026-125110 CVSS Score: 5.3 Published: 2026-11-10 CVE-2026-125110 is a path canonicalization mismatch

CVE-2026-125110: Path Canonicalization Mismatch and Security Header Bypass in Rack::Static

Vulnerability ID: CVE-2026-125110
CVSS Score: 5.3
Published: 2026-11-10

CVE-2026-125110 is a path canonicalization mismatch vulnerability in Rack (specifically within the Rack::Static middleware component). When serving static files, Rack normalizes the requested URL path to resolve the physical file on disk, but evaluates configured path-specific header rules against an unnormalized, raw path that has only undergone URL percent-decoding. Unauthenticated remote attackers can exploit this discrepancy by injecting raw or percent-encoded dot-segments into HTTP requests, causing Rack to serve restricted static assets without their intended security headers.

TL;DR

An order-of-operations flaw in Rack::Static (CWE-180) causes path-specific header rules to be evaluated before dot-segment path normalization. Attackers can use traversal sequences like /css/../admin/secret.html to retrieve static files stripped of protective HTTP headers such as Content-Security-Policy, X-Frame-Options, and restrictive Cache-Control directives.

⚠️ Exploit Status: POC

Technical Details

  • CVE / Advisory ID: CVE-2026-125110 / GHSA-wvg4-6p58-3gh3
  • Weakness Class: CWE-180 (Incorrect Behavior Order: Validate Before Canonicalize)
  • Affected Component: Rack::Static#applicable_rules (lib/rack/static.rb)
  • Attack Vector: Network (Unauthenticated HTTP GET with raw or encoded dot-segments)
  • CVSS v3.1 Score: 5.3 Medium (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N)
  • EPSS Score: 0.25% (16.56th Percentile)
  • Security Impact: Bypass of path-specific HTTP security and caching headers (CSP, X-Frame-Options, Cache-Control)
  • Patched Versions: Rack 2.2.25, 3.1.23, 3.2.8

Affected Systems

  • Ruby Rack (rack RubyGem)
  • Ruby on Rails / Sinatra / Rack-based web applications utilizing Rack::Static with path-specific header_rules
  • rack: < 2.2.25 (Fixed in: 2.2.25)
  • rack: >= 3.0, < 3.1.23 (Fixed in: 3.1.23)
  • rack: >= 3.2, < 3.2.8 (Fixed in: 3.2.8)

Code Analysis

Commit: 18a07fe

Normalize path using Rack::Utils.clean_path_info in Rack::Static#applicable_rules before matching header rules

File: lib/rack/static.rb
@@ -168,7 +168,7 @@ def call(env)

     # Convert HTTP header rules to HTTP headers
     def applicable_rules(path)
-      path = ::Rack::Utils.unescape_path(path)
+      path = ::Rack::Utils.clean_path_info(::Rack::Utils.unescape_path(path))

       @header_rules.find_all do |rule, new_headers|
         case rule

Commit: 9d7f194

Backport fix for Rack::Static#applicable_rules path normalization mismatch

File: lib/rack/static.rb
@@ -168,7 +168,7 @@ def call(env)

     # Convert HTTP header rules to HTTP headers
     def applicable_rules(path)
-      path = ::Rack::Utils.unescape_path(path)
+      path = ::Rack::Utils.clean_path_info(::Rack::Utils.unescape_path(path))

       @header_rules.find_all do |rule, new_headers|
         case rule

Commit: e88097c

Backport fix for Rack::Static#applicable_rules path normalization mismatch (2.2 branch)

File: lib/rack/static.rb
@@ -168,7 +168,7 @@ def call(env)

     # Convert HTTP header rules to HTTP headers
     def applicable_rules(path)
-      path = ::Rack::Utils.unescape_path(path)
+      path = ::Rack::Utils.clean_path_info(::Rack::Utils.unescape_path(path))

       @header_rules.find_all do |rule, new_headers|
         case rule

Exploit Details

  • GitHub: Official upstream regression test suite in test/spec_static.rb demonstrating four dot-segment and percent-encoded bypass payloads.

Mitigation Strategies

  • Upgrade the Rack gem to a patched release (2.2.25, 3.1.23, or 3.2.8) to ensure path canonicalization occurs before header rule matching.
  • Offload static asset serving and security header enforcement to an upstream reverse proxy (such as NGINX or Envoy) or CDN that normalizes URI paths prior to rule evaluation.
  • Invert Rack::Static header rule logic so that restrictive security and caching headers are applied globally via the :all rule, rather than relying on path-specific overrides.
  • Move sensitive static documents and user-uploaded files out of Rack::Static directories and serve them via authenticated controller endpoints.

Remediation Steps:

  1. Audit the application's Gemfile.lock to determine if an affected version of rack (< 2.2.25, >= 3.0 < 3.1.23, or >= 3.2 < 3.2.8) is installed.
  2. Inspect config.ru and environment configuration files for uses of Rack::Static containing path-specific :header_rules options.
  3. Run bundle update rack to upgrade to version 2.2.25, 3.1.23, or 3.2.8 (or higher) depending on your active release branch.
  4. Verify that automated test suites pass and redeploy the updated application containers or server processes.
  5. Purge upstream CDN or reverse proxy caches if sensitive static files may have been publicly cached due to previous Cache-Control rule bypasses.

References

Read the full report for CVE-2026-125110 on our website for more details including interactive diagrams and full exploit analysis.

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.