GHSA-qfgr-crr9-7r49 CVE-2026-32762
Rack: Forwarded Header semicolon injection enables Host and Scheme spoofing
- Severity
- 4.8 / 10
- Medium · CVSS 3.1
- Exploit chance (EPSS)
- 0.19%
- Chance of exploitation in the next 30 days. Higher than 8.17% of scored vulnerabilities.
- Known exploited
- No
- Not in CISA's catalog
- Weakness
- CWE-436 Interpretation Conflict
- Fix
3.1.21- Upgrade rack to this version or later
Description
Summary
Rack::Utils.forwarded_values parses the RFC 7239 Forwarded header by splitting on semicolons before handling quoted-string values. Because quoted values may legally contain semicolons, a header such as:
Forwarded: for="127.0.0.1;host=evil.com;proto=https"
can be interpreted by Rack as multiple Forwarded directives rather than as a single quoted for value.
In deployments where an upstream proxy, WAF, or intermediary validates or preserves quoted Forwarded values differently, this discrepancy can allow an attacker to smuggle host, proto, for, or by parameters through a single header value.
Details
Rack::Utils.forwarded_values processes the header using logic equivalent to:
forwarded_header.split(';').each_with_object({}) do |field, values|
field.split(',').each do |pair|
pair = pair.split('=').map(&:strip).join('=')
return nil unless pair =~ /\A(by|for|host|proto)="?([^"]+)"?\Z/i
(values[$1.downcase.to_sym] ||= []) << $2
end
end
The method splits on ; before it parses individual name=value pairs. This is inconsistent with RFC 7239, which permits quoted-string values, and quoted strings may contain semicolons as literal content.
As a result, a header value such as:
Forwarded: for="127.0.0.1;host=evil.com;proto=https"
is not treated as a single for value. Instead, Rack may interpret it as if the client had supplied separate for, host, and proto directives.
This creates an interpretation conflict when another component in front of Rack treats the quoted value as valid literal content, while Rack reparses it as multiple forwarding parameters.
Impact
Applications that rely on Forwarded to derive request metadata may observe attacker-controlled values for host, proto, for, or related URL components.
In affected deployments, this can lead to host or scheme spoofing in derived values such as req.host, req.scheme, req.base_url, or req.url. Applications that use those values for password reset links, redirects, absolute URL generation, logging, IP-based decisions, or backend requests may be vulnerable to downstream security impact.
The practical security impact depends on deployment architecture. If clients can already supply arbitrary trusted Forwarded parameters directly, this bug may not add meaningful attacker capability. The issue is most relevant where an upstream component and Rack interpret the same Forwarded header differently.
Mitigation
- Update to a patched version of Rack that parses
Forwardedquoted-string values before splitting on parameter delimiters. - Avoid trusting client-supplied
Forwardedheaders unless they are normalized or regenerated by a trusted reverse proxy. - Prefer stripping inbound
Forwardedheaders at the edge and reconstructing them from trusted proxy metadata. - Avoid using
req.host,req.scheme,req.base_url, orreq.urlfor security-sensitive operations unless the forwarding chain is explicitly trusted and validated.
Affected versions
RubyGems
How to fix
Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.
rack RubyGems → 3.1.21
- bundler
bundle update rack # Gemfile: gem "rack", ">= 3.1.21"
Severity breakdown
CVSS 3.1 4.8
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N
- Attack vector
- Network
- Attack complexity
- High
- Privileges required
- None
- User interaction
- None
- Scope
- Unchanged
- Confidentiality
- Low
- Integrity
- Low
- Availability
- None
Weakness
CWE-436: Interpretation Conflict
Product A handles inputs or steps differently than Product B, which causes A to perform incorrect actions based on its perception of B's state.
References
Advisories
Packages
Other links
Timeline
- Published
- Last updated by the source
- Latest EPSS score
Related advisories
| Advisory | Severity | Why it's related |
|---|---|---|
| GHSA-g2pf-xv49-m2h5 Rack::Request accepts invalid Host characters, enabling host allowlist bypass | Medium | Also affects rack |
| GHSA-v6x5-cg8r-vv6x Rack's multipart header parsing allows Denial of Service via escape-heavy quoted parameters | High | Also affects rack |
| GHSA-rx22-g9mx-qrhv Rack's improper unfolding of folded multipart headers preserves CRLF in parsed parameter values | Medium | Also affects rack |
| GHSA-q2ww-5357-x388 Rack has Content-Length mismatch in Rack::Files error responses | Medium | Also affects rack |
| GHSA-qv7j-4883-hwh7 Rack::Sendfile header-based X-Accel-Mapping regex injection enables unauthorized X-Accel-Redirect | High | Also affects rack |
| GHSA-8vqr-qjwx-82mw Rack's multipart parsing without Content-Length header allows unbounded chunked file uploads | High | Also affects rack |
| GHSA-x8cg-fq8g-mxfx Rack's multipart byte range processing allows denial of service via excessive overlapping ranges | High | Also affects rack |
| GHSA-q4qf-9j86-f5mh Rack:: Static header_rules bypass via URL-encoded paths | Medium | Also affects rack |
MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.
Check your repos with MergeHarbor