Rack: ArgumentError: invalid byte sequence in UTF-8

Created on 30 Mar 2014  ยท  6Comments  ยท  Source: rack/rack

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

Most helpful comment

Just leaving this in case of anyone is having trouble with Rails: https://github.com/whitequark/rack-utf8_sanitizer/

:heart:

All 6 comments

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mwpastore picture mwpastore  ยท  3Comments

oniofchaos picture oniofchaos  ยท  5Comments

boazsegev picture boazsegev  ยท  13Comments

ioquatix picture ioquatix  ยท  5Comments

Hirurg103 picture Hirurg103  ยท  13Comments