{"id":"CVE-2026-125108","aliases":["GHSA-p8x9-v4hv-2w4g"],"url":"https://o3.security/vulnerability/CVE-2026-125108","summary":"Rack: Multipart boundary ambiguity guard in Rack::Multipart::Parser can be bypassed with a quoted boundary value, allowing WAF bypass","details":"## Summary\n\nThe guard added for CVE-2026-26961 (GHSA-vgpv-f759-9wx3), which rejects multipart requests with more than one `boundary` parameter, only inspects the part of the `Content-Type` header after the boundary it extracts. A `Content-Type` whose first `boundary` parameter is empty or begins with a quote, semicolon, or comma is skipped by the extraction pattern, so a second `boundary` parameter is accepted silently and Rack parses the body with a boundary that a conforming parser would not derive from the header.\n\n## Details\n\n`Rack::Multipart::Parser.parse_boundary` extracts the boundary with a regular expression that uses a lazy prefix and a value class excluding `\"`, `;`, and `,`. For a header such as `multipart/form-data; boundary=\";boundary=AaB03x\"` or `multipart/form-data; boundary=; boundary=AaB03x`, the pattern skips the first `boundary=` and anchors on the second, and the subsequent check for another `boundary=` in the remaining text finds nothing. Rack then uses `AaB03x`.\n\nRFC 9110 parses the first header as a single parameter whose value is `;boundary=AaB03x`, which is not a legal boundary under RFC 2046, so the only conformant outcome is rejection. Inspecting intermediaries that implement the standard grammar, such as ModSecurity, see a different boundary or no multipart body at all.\n\nThe fix counts `boundary=` occurrences across the entire header value and rejects the request when there is more than one.\n\n## Impact\n\nAs with CVE-2026-26961, an attacker can craft a multipart request that a web application firewall or other inspecting proxy in front of a Rack application interprets differently from Rack, so form fields and file uploads reach the application without inspection. Rack itself grants no capability beyond that of a well-formed request with the same body. All supported versions, including 2.2, are affected.\n\n## Mitigation\n\n* Update to a patched version of Rack.\n* Reject requests whose `Content-Type` contains more than one `boundary` parameter at the reverse proxy.","published":"2026-11-09T21:55:20.600Z","modified":"2026-11-10T10:46:51.545448311Z","cvss":{"score":3.7,"severity":"LOW","vector":"CVSS:3.1/AV:N/AC:H/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/19a1a19cb4da97d61c8d5effeb2e927c44370ae9","label":"rack/rack@19a1a19"},"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/125xxx/CVE-2026-125108.json"},{"type":"FIX","url":"https://github.com/rack/rack/commit/19a1a19cb4da97d61c8d5effeb2e927c44370ae9"},{"type":"FIX","url":"https://github.com/rack/rack/commit/a29512324265790a5536b830490075d0d79323be"},{"type":"FIX","url":"https://github.com/rack/rack/commit/d5e928b803da30b8e40171dbd4be39bed7daa6fa"},{"type":"WEB","url":"https://github.com/rack/rack/releases/tag/v2.2.25"},{"type":"WEB","url":"https://github.com/rack/rack/releases/tag/v3.1.23"},{"type":"WEB","url":"https://github.com/rack/rack/releases/tag/v3.2.8"},{"type":"ADVISORY","url":"https://github.com/rack/rack/security/advisories/GHSA-p8x9-v4hv-2w4g"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-125108"},{"type":"PACKAGE","url":"https://github.com/rack/rack"},{"type":"WEB","url":"https://github.com/rubysec/ruby-advisory-db/blob/master/gems/rack/GHSA-p8x9-v4hv-2w4g.yml"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-11-10T10:46:51.545448311Z"}}