Skip to content

Strong Parameters in Rails 4

On the 4 March 2012, Egor Homakov took advantage of a mass assignment vulnerability to add his public key to the Rails repository, thereby giving himself commit access to Rails. It appears he carried out the exploit when the issue he raised in Github was closed as a “won’t fix”.

To understand the issue, you need to understand how Rails makes it easy to interact with the database. If you have a form to create a model, Rails will pass a hash of parameters on the form being submitted. If you check your logs when submitting a form, you will see something like this for say a User model:

:user => {:name => "Robin Fisher", :email => "robinjfisher@gmail.com", :hometown => "London"}

In the controller, you can access this hash to create or update your user:

def create
  @user = User.create(params[:user])
end

At the time, Rails had a permissive design in that unless defined otherwise, any attributes on our User model could be set through mass assignment. If you had an admin attribute on your User model, a hacker could manipulate the form or use the command line to update that attribute by setting the admin attribute to true.

Rails did have methods to prevent this. A developer could use the attr_accessible method to whitelist attributes that could be updated via mass assignment or the attr_protected method to blacklist attributes. Homakov felt however that leaving this to the developer was the wrong choice and to prove his point, made a couple of educated guesses as to Github’s database design to exploit the vulnerability and add his public key to the Rails repository which gave him commit access.

Following this, Rails was updated so that it was secure by default. Unless an attribute was listed in an attr_accessible method, that attribute could not be updated via mass assignment. And so it was.

There had been much discussion as to whether this control sat better in a Controller or Model. For Rails, the decision was made to put this control into the Controller. When Rails 4 is released, it will ship with the strong_parameters gem built into the core.

It has of course always been possible to define this protection in the controller. It is possible to use the slice extension to Ruby’s Hash class to return only the parameters you want:

def create
  @user = User.create(user_params)
end

private

def user_params
  params[:user].slice(:name, :email, :hometown)
end

This was not without risks.

The strong_parameters gem introduction states:

With this plugin Action Controller parameters are forbidden to be used in Active Model mass assignments until they have been whitelisted. This means you’ll have to make a conscious choice about which attributes to allow for mass updating and thus prevent accidentally exposing that which shouldn’t be exposed.

In addition, parameters can be marked as required and flow through a predefined raise/rescue flow to end up as a 400 Bad Request with no effort.

In our controller, we would now define our create action as follows:

def create
  User.create(user_params)
end

private

def user_params
  params.require(:user).permit(:name, :email, :hometown)
end

This will create our user provided that:

  1. The parameters hash contains a user key; and
  2. The hash does not contain any keys other than those permitted

It’s possible to start preparing your application for Rails 4 by incorporating this gem into your Rails 3 application. Follow the instructions for installing the gem and then follow the example above to set your permitted attributes at a controller level.

When Rails 4 is released, you will simply need to remove the gem from your Gemfile.

If you enjoyed this post, you should sign up to be notified when my book, Real World Development with Ruby on Rails, is released in May 2013. The book and full source code to the application we develop in it will be just $39 with added value packages also available.

3 Comments Post a comment
  1. Reblogged this on Ruby on Rails Help and commented:
    The story behind Strong Parameters in Rails 4

    January 7, 2014

Trackbacks & Pingbacks

  1. Perbedaan metode POST dan GET
  2. DevNews – 06/03/2013 | Code Samurai

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 169 other followers