ACTIONPACK · GHSA-2gff-2mmg-m73p · Package
FIX → 8.1.4.1
Rails 8.1.0 through 8.1.4 reads the client IP from the Forwarded header ahead of X-Forwarded-For when Rack 3 is in use. An unauthenticated attacker who can send a Forwarded header through a proxy that passes it on can set request.remote_ip to any address, which can bypass IP-based access control and rate limits and falsify audit logs.
first public Nov 4, 2026 · 1 source
Could this affect your app?
Free first check from your website. Connect your repo for the full answer.
Applications running Rails 8.1.0 through 8.1.4 with Rack 3, served behind a proxy that passes a client-supplied Forwarded header through unchanged, and that use request.remote_ip for access control, rate limiting or auditing. The fix detects a spoofed Forwarded header only when the proxy also sets X-Forwarded-For, so an app whose proxy sets no X-Forwarded-For stays exposed after upgrading unless the proxy strips Forwarded. Apps on Rack 2.2 or on Rails 8.0 are not affected.
Not affected if default-proxy-strips-forwarded, not-using-remote-ip, rack-2
Who cares actionpack, rails, rate-limiting, ruby, self-hosted
Gemfile.lock for actionpack between 8.1.0 and 8.1.4, and confirm Rack 3 is in use (rack 3.x in Gemfile.lock).Forwarded header.Since Rails 8.1.0, ActionDispatch::RemoteIp derives request.remote_ip from Rack::Request#forwarded_for, which under Rack 3 reads the RFC 7239 Forwarded header in preference to X-Forwarded-For. When a reverse proxy appends the client address to X-Forwarded-For but passes a client-supplied Forwarded header through unchanged, request.remote_ip returns an address chosen by the client, and the IP spoofing check does not raise, because it compares only Client-Ip with the forwarded addresses. An unauthenticated attacker could therefore spoof request.remote_ip, possibly bypassing IP-based access controls and rate limits keyed on the client address (including the default by: of rate_limit), and falsifying the client address in logs.
Check it with your coding agent
It reads this page and tells you if your code is affected.
Are you affected?
Ask from here. InfraStack checks the affected versions against your stack and answers in your inbox.
InfraStack checks the affected versions against your stack and answers in Slack, with the evidence and the fix.
request.remote_ip for access control, rate limiting, or auditing.Upgrade to 8.1.4.1
actionpack 8.1.4.1Forwarded header.X-Forwarded-For: set Rack::Request.forwarded_priority = [:x_forwarded] in an initializer (Rack 3.0.0 and later; this also makes Rack ignore Forwarded for scheme, host and port).The 8.1.0 change (2d084af8) switched ActionDispatch::RemoteIp from reading X-Forwarded-For directly to Rack's forwarded_for, in order to reuse Rack's port handling. Rails continues to honor Forwarded, the standard header.
In the fixed releases, when config.action_dispatch.ip_spoofing_check is enabled (the default), ActionDispatch::RemoteIp also compares the first untrusted client address in Forwarded with the first untrusted client address in X-Forwarded-For, as exact strings, and raises ActionDispatch::RemoteIp::IpSpoofAttackError when both headers are present and the addresses differ. Deployments whose proxies report the client address inconsistently between the two headers will receive this error after upgrading. See the actionpack CHANGELOG.
An application is affected if it meets all of these requirements:
forwarded_for reads only X-Forwarded-For.Forwarded header.request.remote_ip for access control, rate limiting, or auditing.The fix detects a spoofed Forwarded header only when the proxy also sets X-Forwarded-For. An application whose proxy passes a client-supplied Forwarded header through and sets no X-Forwarded-For remains exposed after upgrading, and should configure the proxy to remove or overwrite Forwarded, or apply the workaround below.
actionpack.Forwarded header.Applications whose proxies set X-Forwarded-For can make Rack ignore the Forwarded header, restoring the client address resolution of Rails 8.0, by setting Rack::Request.forwarded_priority = [:x_forwarded] in an initializer. This setting is available in Rack 3.0.0 and later, and it also causes Rack to ignore Forwarded when determining the request scheme, host, and port.
The fixed releases are available at the normal locations.
Patches for those who cannot upgrade at once:
This issue was responsibly reported by HackerOne researcher luryus.