VDB
Sign up
MEDIUM4.8

GHSA-qfgr-crr9-7r49

Rack: Forwarded Header semicolon injection enables Host and Scheme spoofing

Quick fix

GHSA-qfgr-crr9-7r49 — rack: upgrade to the fixed version with the command below.

bundle update rack

Details

## 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:

```http 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:

```ruby 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:

```http 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 `Forwarded` quoted-string values before splitting on parameter delimiters. * Avoid trusting client-supplied `Forwarded` headers unless they are normalized or regenerated by a trusted reverse proxy. * Prefer stripping inbound `Forwarded` headers at the edge and reconstructing them from trusted proxy metadata. * Avoid using `req.host`, `req.scheme`, `req.base_url`, or `req.url` for security-sensitive operations unless the forwarding chain is explicitly trusted and validated.

Are you affected?

Enter the version of the package you're using.

Affected packages

RubyGems/rack
Introduced in: 3.0.0.beta1Fixed in: 3.1.21
Fixbundle update rack
RubyGems/rack
Introduced in: 3.2.0Fixed in: 3.2.6
Fixbundle update rack

References