Old Errata Note

Erratum regarding code examples in Chapter 4, specifically section 4.3:

TL;DR: To make Rails 3.2 behave the same as earlier versions with respect to mass-assignment of attributes, comment out the following line in your app's config/environments/development.rb:

BEFORE:
      config.active_record.mass_assignment_sanitizer = :strict

AFTER:
      # config.active_record.mass_assignment_sanitizer = :strict

Explanation:  ActiveRecord calls such as create, create!, update_attributes, and so on all perform "mass assignment": they take a hash of attribute name => value pairs, and assign all the corresponding attributes of the model from that hash, as in  Movie.create!(:title => 'Star Wars', :rating => 'PG')

As explained in section 5.2 and repeated in section 12.9, there is a security risk if some of those attributes are not supposed to be user-assignable (for example, imagine an attribute is_admin on User, which determines if the user has admin superpowers on the site). Even though the web form UI may not expose that attribute, it would be trivial for a malicious user to manually create an HTTP POST request that includes a new value for the is_admin attribute.

To remedy this, Rails provides attr_protected and attr_accessible, which section 5.2 explains.  But starting with Rails 3.2, by default you will get an exception  if you try to mass-assign attributes that have not been named in either  attr_accessible or attr_protected.  This behavior is turned on in development and testing mode, but turned off in production; the goal is to warn you at development time that you have attributes that you haven't explicitly marked as either safe or unsafe to mass-assign.

This new default behavior was motivated in part by a successful attack against GitHub several months ago that exploited the old default behavior. (The episode, and more detail on the above technical discussion, are well summarized in this blog post.)  There was a lot of debate as to whose fault it was. Some said the fault lay with the GitHub developers, who were irresponsible in not using attr_accessible or attr_protected explicitly. Others said the fault lay with the Rails developers for making the default behavior the insecure one and requiring extra work to get the secure behavior.  Ultimately the latter faction won.
Comments