{"id":"CVE-2026-125110","aliases":["GHSA-wvg4-6p58-3gh3"],"url":"https://o3.security/vulnerability/CVE-2026-125110","summary":"Rack: Rack::Static header_rules bypass via dot-segment normalization mismatch","details":"## Summary\n\n`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.\n\nThis allows an attacker to receive a protected static file without the security headers configured for it.\n\n## Details\n\n`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.\n\nThe 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.\n\n## Impact\n\nApplications 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.\n\n## Mitigation\n\n* Update to a patched version of Rack in which `header_rules` are matched against the same normalized path used to serve the file.\n* Reject requests containing dot segments at a reverse proxy or application boundary.\n* Do not rely solely on `Rack::Static` `header_rules` to prevent inline rendering of untrusted uploads; serve them from a separate origin.\n\n## Credit\n* Reporter and Remediation developer","published":"2026-11-09T22:00:40.811Z","modified":"2026-11-10T10:47:01.771012542Z","cvss":{"score":5.3,"severity":"MEDIUM","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N"},"epss":null,"cisaKev":null,"exploitsKnown":null,"affectedPackages":[{"ecosystem":"RubyGems","name":"rack","fixedVersion":"2.2.25"},{"ecosystem":"RubyGems","name":"rack","fixedVersion":"3.1.23"},{"ecosystem":"RubyGems","name":"rack","fixedVersion":"3.2.8"}],"fix":{"url":"https://github.com/rack/rack/commit/18a07fe553afb4d8a678d6a948cd6ba1e11e28be","label":"rack/rack@18a07fe"},"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/125xxx/CVE-2026-125110.json"},{"type":"FIX","url":"https://github.com/rack/rack/commit/18a07fe553afb4d8a678d6a948cd6ba1e11e28be"},{"type":"FIX","url":"https://github.com/rack/rack/commit/9d7f19484ffd5ed5e032678c26ee6eff96d3a0a3"},{"type":"FIX","url":"https://github.com/rack/rack/commit/e88097ccb88be44d06d47b42daffe04929516ee4"},{"type":"ADVISORY","url":"https://github.com/rack/rack/security/advisories/GHSA-wvg4-6p58-3gh3"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-125110"},{"type":"PACKAGE","url":"https://github.com/rack/rack"},{"type":"WEB","url":"https://github.com/rubysec/ruby-advisory-db/blob/master/gems/rack/GHSA-wvg4-6p58-3gh3.yml"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-11-10T10:47:01.771012542Z"}}