GHSA-wvg4-6p58-3gh3MediumCVSS 5.3

Rack: Rack::Static header_rules bypass via dot-segment normalization mismatch

Published
November 10, 2026
Last Modified
November 10, 2026

🔗 CVE IDs covered (1)

📋 Description

Summary

Rack::Static normalizes the request path with Utils.clean_path_info when deciding which file to serve, but matches header_rules against a path that is only URL-decoded. A request containing dot segments, raw or percent-encoded, is served the normalized target file while the header rules for that file's location are not applied.

This allows an attacker to receive a protected static file without the security headers configured for it.

Details

Rack::Static#call computes the served path as Utils.clean_path_info(Utils.unescape_path(path)). Rack::Static#applicable_rules applies only Utils.unescape_path before testing string and regular expression rules. A request for /assets/../uploads/file.html or /assets/..%2fuploads/file.html is served as uploads/file.html, but the decoded path /assets/../uploads/file.html does not start with uploads, so a rule scoped to that directory never matches.

The fix for CVE-2026-34786 (GHSA-q4qf-9j86-f5mh) added URL decoding to rule matching but did not add dot segment normalization, so versions that include that fix remain affected.

Impact

Applications that use Rack::Static header_rules to attach security-relevant headers to particular paths or file types are affected. An unauthenticated attacker who knows the path of a protected file can request it through a dot segment path and receive it without those headers, for example without Content-Disposition: attachment or a restrictive Content-Security-Policy that prevents uploaded HTML from rendering inline. The file itself is served unchanged. Applications that do not use path-specific header_rules are not affected.

Mitigation

  • Update to a patched version of Rack in which header_rules are matched against the same normalized path used to serve the file.
  • Reject requests containing dot segments at a reverse proxy or application boundary.
  • Do not rely solely on Rack::Static header_rules to prevent inline rendering of untrusted uploads; serve them from a separate origin.

Credit

  • Reporter and Remediation developer

🎯 Affected products3

  • rubygems/rack:< 2.2.25
  • rubygems/rack:>= 3.0.0, < 3.1.23
  • rubygems/rack:>= 3.2.0, < 3.2.8

🔗 References (7)