Fix NoMethodError in Request#wrap_ipv6 when x-forwarded-host is empty#2270
Conversation
NoMethodError in Request#forwarded_authority when x-forwarded-host is emptyNoMethodError in Request#wrap_ipv6 when x-forwarded-host is empty
|
Is the problem really in Rack? Can you provide the full backtrace? I tried to reproduce it but couldn't: $ echo 'require "rack";app { |env| req = ::Rack::Request.new(env); pp req.host_with_port; [200, {}, ["OK"]] }' | puma --config /dev/stdin --log-requests --port 8888
Puma starting in single mode...
* Puma version: 6.5.0 ("Sky's Version")
* Ruby version: ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [arm64-darwin23]
* Min threads: 0
* Max threads: 5
* Environment: development
* PID: 63959
* Listening on http://0.0.0.0:8888
Use Ctrl-C to stop
"localhost:8888"
127.0.0.1 - - [26/Dec/2024:16:22:15 +0100] "GET / HTTP/1.1" 200 - 0.0225
"\"\""
127.0.0.1 - - [26/Dec/2024:16:22:33 +0100] "GET / HTTP/1.1" 200 - 0.0004$ curl -H 'x-forwarded-host: ' localhost:8888
OK
$ curl -H 'x-forwarded-host: ""' localhost:8888
OK |
|
@dentarg server # puma-config.rb
require 'rack'
app { |env|
req = ::Rack::Request.new(env);
pp req.env['HTTP_X_FORWARDED_HOST']
pp req.env['HTTP_X_FORWARDED_HOST'].class
begin
pp req.host_with_port
[200, {}, ["OK"]]
rescue => e
pp e
[500, {}, ['ERROR']]
end
}$ puma --config puma-config.rb --log-requests --port 8888
Puma starting in single mode...
* Puma version: 6.5.0 ("Sky's Version")
* Ruby version: ruby 3.2.3 (2024-01-18 revision 52bb2ac0a6) [x86_64-linux]
* Min threads: 0
* Max threads: 5
* Environment: development
* PID: 18853
* Listening on http://0.0.0.0:8888
Use Ctrl-C to stop
""
String
#<NoMethodError: undefined method `start_with?' for nil:NilClass>
127.0.0.1 - - [27/Dec/2024:07:02:47 +0900] "GET / HTTP/1.1" 500 - 0.0452
nil
NilClass
"localhost:8888"
127.0.0.1 - - [27/Dec/2024:07:04:12 +0900] "GET / HTTP/1.1" 200 - 0.0007request $ ruby -r 'net/http' -e "pp Net::HTTP.get(URI.parse('http://localhost:8888'), { 'x-forwarded-host': '' })"
"ERROR"
$ curl -H 'x-forwarded-host: ' localhost:8888
OK |
|
Here is an example of outputting # puma-config.rb
require 'rack'
app { |env|
req = ::Rack::Request.new(env);
pp req.env['HTTP_X_FORWARDED_HOST']
pp req.env['HTTP_X_FORWARDED_HOST'].class
begin
pp req.host_with_port
[200, {}, ["OK"]]
rescue => e
# pp e
pp e.backtrace
[500, {}, ['ERROR']]
end
}$ puma --config puma-config.rb --log-requests --port 8888
Puma starting in single mode...
* Puma version: 6.5.0 ("Sky's Version")
* Ruby version: ruby 3.2.3 (2024-01-18 revision 52bb2ac0a6) [x86_64-linux]
* Min threads: 0
* Max threads: 5
* Environment: development
* PID: 22231
* Listening on http://0.0.0.0:8888
Use Ctrl-C to stop
""
String
["/home/oieioi/.anyenv/envs/rbenv/versions/3.2.3/lib/ruby/gems/3.2.0/gems/rack-3.1.8/lib/rack/request.rb:637:in `wrap_ipv6'",
"/home/oieioi/.anyenv/envs/rbenv/versions/3.2.3/lib/ruby/gems/3.2.0/gems/rack-3.1.8/lib/rack/request.rb:402:in `block in forwarded_authority'",
"/home/oieioi/.anyenv/envs/rbenv/versions/3.2.3/lib/ruby/gems/3.2.0/gems/rack-3.1.8/lib/rack/request.rb:394:in `each'",
"/home/oieioi/.anyenv/envs/rbenv/versions/3.2.3/lib/ruby/gems/3.2.0/gems/rack-3.1.8/lib/rack/request.rb:394:in `forwarded_authority'",
"/home/oieioi/.anyenv/envs/rbenv/versions/3.2.3/lib/ruby/gems/3.2.0/gems/rack-3.1.8/lib/rack/request.rb:267:in `authority'",
"/home/oieioi/.anyenv/envs/rbenv/versions/3.2.3/lib/ruby/gems/3.2.0/gems/rack-3.1.8/lib/rack/request.rb:322:in `host_with_port'",
"puma-config.rb:8:in `block in _load_from'",
"/home/oieioi/.anyenv/envs/rbenv/versions/3.2.3/lib/ruby/gems/3.2.0/gems/puma-6.5.0/lib/puma/commonlogger.rb:47:in `call'",
"/home/oieioi/.anyenv/envs/rbenv/versions/3.2.3/lib/ruby/gems/3.2.0/gems/puma-6.5.0/lib/puma/configuration.rb:279:in `call'",
"/home/oieioi/.anyenv/envs/rbenv/versions/3.2.3/lib/ruby/gems/3.2.0/gems/puma-6.5.0/lib/puma/request.rb:99:in `block in handle_request'",
"/home/oieioi/.anyenv/envs/rbenv/versions/3.2.3/lib/ruby/gems/3.2.0/gems/puma-6.5.0/lib/puma/thread_pool.rb:389:in `with_force_shutdown'",
"/home/oieioi/.anyenv/envs/rbenv/versions/3.2.3/lib/ruby/gems/3.2.0/gems/puma-6.5.0/lib/puma/request.rb:98:in `handle_request'",
"/home/oieioi/.anyenv/envs/rbenv/versions/3.2.3/lib/ruby/gems/3.2.0/gems/puma-6.5.0/lib/puma/server.rb:468:in `process_client'",
"/home/oieioi/.anyenv/envs/rbenv/versions/3.2.3/lib/ruby/gems/3.2.0/gems/puma-6.5.0/lib/puma/server.rb:249:in `block in run'",
"/home/oieioi/.anyenv/envs/rbenv/versions/3.2.3/lib/ruby/gems/3.2.0/gems/puma-6.5.0/lib/puma/thread_pool.rb:166:in `block in spawn_thread'"]
127.0.0.1 - - [27/Dec/2024:07:27:18 +0900] "GET / HTTP/1.1" 500 - 0.0261 |
jeremyevans
left a comment
There was a problem hiding this comment.
Thanks for the patch! I agree this is a bug that we should fix.
TIL, thanks! |
|
You can trigger the bug with curl like this: |
Thank you! I was able to reproduce it with that command. |
mikegee
left a comment
There was a problem hiding this comment.
Seems legit to me too. Are there any concerns preventing merge?
|
@jeremyevans @dentarg What can I do for this PR? |
…d-host` is empty Currently, sending a request with an empty `x-forwarded-host` causes nil access in `wrap_ipv6`, resulting in a `NoMethodError`. Added a nil check in `forwarded_authority` to prevent this issue.
Co-authored-by: Jeremy Evans <code@jeremyevans.net>
3a75f53 to
02ece97
Compare
|
Thanks for your contribution. |
Currently, sending a request with an empty
x-forwarded-hostcauses aNoMethodErrordue to nil access inwrap_ipv6. Sinceforwarded_authorityis the only method that could pass nil towrap_ipv6, I added a nil check inforwarded_authorityto prevent this issue.For example, when making a request to a Rack server using JavaScript, an error occurred on the server.