We write about Ruby on Rails, React.js, React Native, remote work, open source, engineering and design.
Rails 4.1 introduced JSON
serialization for cookies. Earlier
all the cookies were serialized using Marshal library of Ruby. The
marshalling of cookies can be
unsafe
because of the possibility of remote code execution vulnerability. So
the change to :json
is welcoming.
The new applications created with Rails 4.1 or 4.2 have :json
as the default
cookies serializer.
rake rails:update
used for upgrading existing Rails apps to new versions rightly changes the
serializer to :json
.
1Rails.application.config.action_dispatch.cookies_serializer = :json
However that change can introduce an issue in the application.
Consider a scenario where the cookies are being used for session
storage. Like many normal Rails apps, the current_user_id
is being stored into the session.
1session[:user_id] = current_user_id
Before Rails 4.1 the cookie will be handled by Marshal serializer.
1cookie = Marshal.dump(current_user_id) # 42 => "\x04\bi/"
2Marshal.load(cookie) # "\x04\bi/" => "42"
After the upgrade the application will try to unserialize cookies using
JSON
which were serialized using Marshal
.
1JSON.parse cookie # Earlier dumped using Marshal
2# JSON::ParserError: 757: unexpected token at i/'
So the deserialization of the existing cookies will fail and users will start getting errors.
To prevent this Rails provides with a hybrid
serializer. The
hybrid
serializer deserializes marshalled cookies and stores
them in JSON format for the next use. All the new cookies will be
serialized in the JSON format. This gives happy path for migrating
existing marshaled cookies to new Rails versions like 4.1 and 4.2.
To use this hybrid serializer, set cookies_serializer config as
:hybrid
as follows:
1Rails.application.config.action_dispatch.cookies_serializer = :hybrid
After this, all the existing marshalled cookies will be migrated to :json
format properly and in the future upgrade of Rails, you can
safely change the config from :hybrid
to :json
which is the
default and safe value of this config.