Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why slicing the params hash poses a security issue on mass-assignment?

The official way of preventing security risks with mass-assignment is using attr_accessible. However, some programmers feel this is not a job for the model (or at least not only for the model). The simplest way of doing it in a controller is slicing the params hash:

@user = User.update_attributes(params[:user].slice(:name))

However the documentation states:

Note that using Hash#except or Hash#slice in place of attr_accessible to sanitize attributes won’t provide sufficient protection.

Why is that? Why a whitelist-slicing of params does not provide enough protection?

UPDATE: Rails 4.0 will ship strong-parameters, a refined slicing of parameters, so I guess the whole slicing thing was not so bad after all.

like image 596
tokland Avatar asked Sep 20 '11 10:09

tokland


3 Answers

The problem with slice and except in controller might occur in combination with accept_nested_attributes_for in your model. If you use nested attributes, you would need to slice parameters on all places, where you update them in controller, which isn't always the easiest task, especially with deeply nested scenarios. With using attr_accesible you don't have this problem.

like image 110
iNecas Avatar answered Nov 10 '22 01:11

iNecas


As of Rails 4, slicing the parameters will be the preferred method of dealing with mass assignment security. The Rails core team has already developed a plugin to deal with this now, and they are working on integrating support for nested attributes and signed forms. Definitely something to check out: http://weblog.rubyonrails.org/2012/3/21/strong-parameters/

like image 20
Joost Baaij Avatar answered Nov 10 '22 03:11

Joost Baaij


Interesting gist from DHH on slicing in controller vs whitelisting alone:

https://gist.github.com/1975644

class PostsController < ActionController::Base
  def create
    Post.create(post_params)
  end

  def update
    Post.find(params[:id]).update_attributes!(post_params)
  end

  private
    def post_params
      params[:post].slice(:title, :content)
    end
end

Comment reinforcing the need to manage this within the controller:

https://gist.github.com/1975644#gistcomment-88369

I personally apply both - attr_accessible with slice to ensure nothing unexpected gets through. Never rely on blacklisting alone!

like image 4
yellowaj Avatar answered Nov 10 '22 02:11

yellowaj