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
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
rake rails:update used for upgrading existing Rails apps to new versions rightly changes the
Rails.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.
session[:user_id] = current_user_id
Before Rails 4.1 the cookie will be handled by Marshal serializer.
cookie = Marshal.dump(current_user_id) # 42 => "\x04\bi/" Marshal.load(cookie) # "\x04\bi/" => "42"
After the upgrade the application will try to unserialize cookies using
JSON which were serialized using
JSON.parse cookie # Earlier dumped using Marshal # 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:
Rails.application.config.action_dispatch.cookies_serializer = :hybrid
After this, all the existing marshalled cookies will be migrated to
format properly and in the future upgrade of Rails, you can
safely change the config from
:json which is the
default and safe value of this config.