Hey guys. Rack gets crazy when you pass invalid UTF-8 string.
You can try with putting this into app URL:
?%28t%B3odei%29
It will brake app with this error: ArgumentError: invalid byte sequence in UTF-8
More details also here: http://dev.mensfeld.pl/2014/03/rack-argument-error-invalid-byte-sequence-in-utf-8/
rack-1.5.2/lib/rack/utils.rb:104โ normalize_params
rack-1.5.2/lib/rack/utils.rb:96โ block in parse_nested_query
rack-1.5.2/lib/rack/utils.rb:93โ each
rack-1.5.2/lib/rack/utils.rb:93โ parse_nested_query
rack-1.5.2/lib/rack/request.rb:373โ parse_query
actionpack-4.0.4/lib/action_dispatch/http/request.rb:321โ parse_query
rack-1.5.2/lib/rack/request.rb:188โ GET
actionpack-4.0.4/lib/action_dispatch/http/request.rb:274โ GET
actionpack-4.0.4/lib/action_dispatch/http/parameters.rb:16โ parameters
actionpack-4.0.4/lib/action_dispatch/http/filter_parameters.rb:37โ filtered_parameters
actionpack-4.0.4/lib/action_controller/metal/instrumentation.rb:22โ process_action
actionpack-4.0.4/lib/action_controller/metal/params_wrapper.rb:250โ process_action
activerecord-4.0.4/lib/active_record/railties/controller_runtime.rb:18โ process_action
actionpack-4.0.4/lib/abstract_controller/base.rb:136โ process
actionpack-4.0.4/lib/abstract_controller/rendering.rb:44โ process
actionpack-4.0.4/lib/action_controller/metal.rb:195โ dispatch
actionpack-4.0.4/lib/action_controller/metal/rack_delegation.rb:13โ dispatch
actionpack-4.0.4/lib/action_controller/metal.rb:231โ block in action
actionpack-4.0.4/lib/action_dispatch/routing/route_set.rb:80โ call
actionpack-4.0.4/lib/action_dispatch/routing/route_set.rb:80โ dispatch
actionpack-4.0.4/lib/action_dispatch/routing/route_set.rb:48โ call
actionpack-4.0.4/lib/action_dispatch/journey/router.rb:71โ block in call
actionpack-4.0.4/lib/action_dispatch/journey/router.rb:59โ each
actionpack-4.0.4/lib/action_dispatch/journey/router.rb:59โ call
actionpack-4.0.4/lib/action_dispatch/routing/route_set.rb:674โ call
omniauth-1.2.1/lib/omniauth/strategy.rb:186โ call!
omniauth-1.2.1/lib/omniauth/strategy.rb:164โ call
rack-canonical-host-0.0.9/lib/rack/canonical_host.rb:19โ call
warden-1.2.3/lib/warden/manager.rb:35โ block in call
warden-1.2.3/lib/warden/manager.rb:34โ catch
warden-1.2.3/lib/warden/manager.rb:34โ call
rack-1.5.2/lib/rack/etag.rb:23โ call
rack-1.5.2/lib/rack/conditionalget.rb:25โ call
rack-1.5.2/lib/rack/head.rb:11โ call
actionpack-4.0.4/lib/action_dispatch/middleware/params_parser.rb:27โ call
actionpack-4.0.4/lib/action_dispatch/middleware/flash.rb:241โ call
rack-1.5.2/lib/rack/session/abstract/id.rb:225โ context
rack-1.5.2/lib/rack/session/abstract/id.rb:220โ call
actionpack-4.0.4/lib/action_dispatch/middleware/cookies.rb:486โ call
activerecord-4.0.4/lib/active_record/query_cache.rb:36โ call
activerecord-4.0.4/lib/active_record/connection_adapters/abstract/connection_pool.rb:626โ call
actionpack-4.0.4/lib/action_dispatch/middleware/callbacks.rb:29โ block in call
activesupport-4.0.4/lib/active_support/callbacks.rb:373โ _run__FRAGMENT__call__callbacks
activesupport-4.0.4/lib/active_support/callbacks.rb:80โ run_callbacks
actionpack-4.0.4/lib/action_dispatch/middleware/callbacks.rb:27โ call
actionpack-4.0.4/lib/action_dispatch/middleware/remote_ip.rb:76โ call
actionpack-4.0.4/lib/action_dispatch/middleware/debug_exceptions.rb:17โ call
actionpack-4.0.4/lib/action_dispatch/middleware/show_exceptions.rb:30โ call
railties-4.0.4/lib/rails/rack/logger.rb:38โ call_app
railties-4.0.4/lib/rails/rack/logger.rb:20โ block in call
activesupport-4.0.4/lib/active_support/tagged_logging.rb:68โ block in tagged
activesupport-4.0.4/lib/active_support/tagged_logging.rb:26โ tagged
activesupport-4.0.4/lib/active_support/tagged_logging.rb:68โ tagged
railties-4.0.4/lib/rails/rack/logger.rb:20โ call
actionpack-4.0.4/lib/action_dispatch/middleware/request_id.rb:21โ call
rack-1.5.2/lib/rack/methodoverride.rb:21โ call
rack-1.5.2/lib/rack/runtime.rb:17โ call
activesupport-4.0.4/lib/active_support/cache/strategy/local_cache.rb:83โ call
rack-1.5.2/lib/rack/sendfile.rb:112โ call
railties-4.0.4/lib/rails/engine.rb:511โ call
railties-4.0.4/lib/rails/application.rb:97โ call
railties-4.0.4/lib/rails/railtie/configurable.rb:30โ method_missing
puma-2.7.1/lib/puma/configuration.rb:68โ call
puma-2.7.1/lib/puma/server.rb:486โ handle_request
puma-2.7.1/lib/puma/server.rb:357โ process_client
puma-2.7.1/lib/puma/server.rb:250โ block in run
puma-2.7.1/lib/puma/thread_pool.rb:92โ call
puma-2.7.1/lib/puma/thread_pool.rb:92โ block in spawn_thread
:+1:
+1
It is a web servers responsibility to translate IO to valid binary representations for the application layer. This isn't the whole picture though, in this case, the webserver has done that - the webserver does not know the encoding of the URI...
It is the responsibility of the IETF to define the validity of URI data in various encodings (not done), and so it is not entirely valid for web servers to make no assumptions for this field for the above...
Rack itself uses a binary regular expression here, which expects binary input strings. This is our response to the above subtleties. In normal operation (say, Webrick + Rack), this error is not raised...
The reason that this error is raised in your application is:
You have middleware in your stack that is forcing this string to UTF-8, even when it is not valid UTF-8. The code that is doing this is bugged.
Observe:
s = "a=\xff"
# => "a=\xFF"
s.force_encoding("binary")
# => "a=\xFF"
s.valid_encoding?
# => true
Rack::Utils.parse_nested_query(s)
# => {"a"=>"\xFF"}
s.force_encoding("utf-8")
# => "a=\xFF"
s.valid_encoding?
# => false
Rack::Utils.parse_nested_query(s)
ArgumentError: invalid byte sequence in UTF-8
from /usr/local/google/home/raggi/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/rack-1.5.2/lib/rack/utils.rb:93:in `split'
from /usr/local/google/home/raggi/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/rack-1.5.2/lib/rack/utils.rb:93:in `parse_nested_query'
from (irb):21
from /usr/local/google/home/raggi/.rbenv/versions/2.0.0-p247/bin/irb:12:in `<main>'
This is a rails bug. Calls to force_encoding should always assert that their output is valid.
@raggi Thx :-) sorry for that - cheers!
You have middleware in your stack that is forcing this string to UTF-8, even when it is not valid UTF-8. The code that is doing this is bugged.
This part does default to UTF-8, though. And thanks to that, trying to do a parse_nested_query with invalid key string will raise ArgumentError as I mentioned in issue #610, without obvious way to change it.
irb(main):003:0> s="\xFF=a"
=> "\xFF=a"
irb(main):004:0> s.force_encoding("binary")
=> "\xFF=a"
irb(main):005:0> s.valid_encoding?
=> true
irb(main):006:0> Rack::Utils.parse_nested_query(s)
ArgumentError: invalid byte sequence in UTF-8
from /home/edho/app/ruby21/lib/ruby/gems/2.1.0/gems/rack-1.5.2/lib/rack/utils.rb:104:in `normalize_params'
from /home/edho/app/ruby21/lib/ruby/gems/2.1.0/gems/rack-1.5.2/lib/rack/utils.rb:96:in `block in parse_nested_query'
from /home/edho/app/ruby21/lib/ruby/gems/2.1.0/gems/rack-1.5.2/lib/rack/utils.rb:93:in `each'
from /home/edho/app/ruby21/lib/ruby/gems/2.1.0/gems/rack-1.5.2/lib/rack/utils.rb:93:in `parse_nested_query'
from (irb):6
from /home/edho/app/ruby21/bin/irb:11:in `<main>'
Just leaving this in case of anyone is having trouble with Rails: https://github.com/whitequark/rack-utf8_sanitizer/
:heart:
Most helpful comment
Just leaving this in case of anyone is having trouble with Rails: https://github.com/whitequark/rack-utf8_sanitizer/
:heart: