Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
attr_accessible on some properties + attr_protected on others makes class 'open-by-default' #7018
If you set attr_accessible on some properties in an ActiveRecord-descended class, and then attr_protected on others - the class becomes 'default-open' - if any properties are missed or added later, they will be accessible by default to MassAssignment.
This undoes the entire point of having put attr_accessible in one's class.
Two possible solutions -
Solution #1 is probably fine - accesses to not
I found this bug in my own code during the development cycle; I liked putting both a
class Thing < ActiveRecord::Base attr_accessible :thingone, :name, :thingtwo, :thingthree # Don't use both attr_accessible and attr_protected!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! attr_protected :status # I was just doing this for symmetry, I guess? belongs_to :user end
You can use mass-assigment to assign to
I agree it seems to me it should raise if you specify both. Or at least issue some sort of warning.
Also agree with @guilleiguaran. If you guys aren't aware, strong_parameters will be available in Rails 4 git://github.com/rails/strong_parameters.git . Both attr_accessible and attr_protected should probably be deprecated in master.
I think we can make attr_protected raise (or perhaps just warn) if called after attr_accessible.
However it's been like this for a very very long time so I wouldn't necessarily suggest that it needed to be urgently fixed or anything. Perhaps just fix the 4.0/plugin code?
You could make the argument that it doesn't need to be fixed very urgently - I get that.
But I do think it should be fixed, and sooner rather than later. Here's why.
You have some statements here that a developer would use in order to take specific steps to secure his/her code.
Those statements won't work in the way that seems most 'obvious' to the developer, thus leaving him/her with effectively insecure code, after the developer has gone to some lengths to secure it. That's dangerous.
Now, it may be the case that the number of times this particular pairing (attr_protected/attr_accessible) is actually used together in live code is pretty rare - if that's true, then I guess there's no rush to fix. But it's not documented that you shouldn't use them together, and someone who might be trying to be 'thorough' (e.g., me) might get bitten by it, and leave a security hole in code that they were trying to be careful with.
That strikes me as the type of problem that should be addressed somewhat swiftly.
It's pretty rare that they're used in the same model. But it's not rare that they're used in subclasses. e.g. attr_accessible declared in AR::Base and attr_protected declared in a particular subclass.
If we could have a patch which distinguished between that case, and the erroneous "declarations in the same file" case, then we could ship that.
The inheritance implementation seems kinda weird too. Consider:
class Inner < ActiveRecord::Base attr_accessible :twiddle_that, :twiddle_this # :superprivate_text is 'protected' end
class Outer < Inner attr_protected :twiddle_this # now what happens? end
And then the following Console actions:
Which is as expected - however -
So a class which inherits from another completely resets the attr_protected/attr_accessible 'state' based on "last-one-first?" That doesn't seem right.
I think if you look at it from the point of view of programmer intent - a derived class ought to only be able to make a 'protected' member of one of its ancestors accessible by explicitly naming it. And setting new levels of attr_accessible/attr_protected on different levels of the class hierarchy ought to only affect that level of the class hierarchy.
I'm open to other interpretations though. I think it all depends on what people are trying to accomplish when they use both attr_accessible and attr_protected - what does the programmer mean? If the behavior matches that intent, then it works the way it should.
As weird as it is, that's defined and documented behaviour that people rely on,
We could make those changes in a 4.1 release of the attribute protection gem, but not at this stage. It's possibly a good idea to investigate the feasiblity of the changes you're outlining in http://github.com/rails/protected_attributes, but not in a maintenance release of a feature that's getting deprecated.