2

Following the ruby on rails guide developer can't mass-assign protected fields but don't get exception trying to do it, right? But in my case mass-assignment different params through new method in rails application:

@edition = Edition.new params[:edition]

raise following exception:

ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: price

Why? Did I understand something incorrectly? Is it a way not to get the mass-assignment exception? It's not convenient to delete protected attributes from hashes before assignments i think.

Update: Edition model:

class Edition < ActiveRecord::Base
  attr_accessible :title, :description
  attr_protected :price
end

params[:edition].inspect:

{"title"=>"t", "description"=>"d", "price"=>"123"}
tiktak
  • 1,801
  • 2
  • 26
  • 46

1 Answers1

3

You are attempting to assign protected attribute price in mass assignment by putting

@edition = Edition.new params[:edition]

That is a mass assignment of variables and in params[:edition] according to your edit, there is the variable price which according to your code cannot be mass assigned.

To fix this you either have to remove the protection on price which I do not think you would want to do or mass-assign only the unprotected variables with new and then assign the protected variable. SO:

    @edition = Edition.new params[:edition].except("price")
    @edition.price = params[:edition]['price']

OR @edition = Edition.new params[:edition], :without_protection => true

EDIT: news.ycombinator.com/item?id=3780963 Rails 3.23 now makes the validation strict by default which raises that exception. The documentation is out of date.

Michael Papile
  • 6,836
  • 30
  • 30
  • ok, but what about examples in ruby on rails guide? You can find the link at the top of the question. They don't do any removing. – tiktak Jun 13 '12 at 20:49
  • Yeah they pass :without_protection with it. The crux of the problem is still the same. You are trying to mass assign a protected variable. You can also bypass the check with :without_protection. The purpose of mass-assignment protection is to avoid someone doing User.update(params) on a REST call and have an attacker pass in :admin=>true when the intent was just to update their password. – Michael Papile Jun 13 '12 at 21:00
  • I think the main thing here is that you need to understand the security risks of mass-assignment and know why you are having this problem. – Michael Papile Jun 13 '12 at 21:02
  • thanks for your help. Please, look at the code example after words 'If you want to set a protected attribute, you will to have to assign it individually'. They don't have any exceptions, do they? Why? – tiktak Jun 13 '12 at 21:41
  • they have the without_protection flag to bypass it, but you really shouldn't do that. But understand that this protection exists because the creator of the model has decided that this field has a potential security threat if it is set with every other variable all at once. That is why they make it explicit to be set. Read about mass-assignment vulnerabilities and you will see what they are doing here and why they are making it difficult. – Michael Papile Jun 13 '12 at 22:30
  • you say "It's not convenient to delete protected attributes from hashes before assignments i think." You are 100% right and that is what they are trying to do. They do not want you to inadvertently set a protected variable through mass-assignment. If you have no need to protect something, remove protection. – Michael Papile Jun 13 '12 at 22:33
  • Sorry, but i really can't see any flag in the code example after the words. Here is the code exactly after them: http://pastebin.com/aBjksWYY . Looks like no exception. ps: it's clear that there is no need to protect price field. It' just an example. – tiktak Jun 13 '12 at 22:56
  • 1
    http://news.ycombinator.com/item?id=3780963 Rails 3.23 now makes the validation strict by default which raises that exception. The documentation is out of date. – Michael Papile Jun 13 '12 at 23:36
  • Oh, Thanks for help. Please, add it to the answer. – tiktak Jun 13 '12 at 23:38
  • 1
    For future Googlers, the params part should be 'params[:edition].except("price")'. Delete returns the value for the deleted key instead of the new hash. The rails function 'except' does just that. – Cody Poll Apr 15 '14 at 23:59