8

I'm fixing some mass assignment vulnerabilities in a client's application and I want to make sure Rails isn't silently dropping attempts to mass assign protected attributes. Instead, I want to throw an exception so I can investigate.

I.e., whenever this would normally appear in the logs:

WARNING: Can't mass-assign these protected attributes: ...

I'd like to throw an exception instead (or in addition)

Edit: I'm using Rails 2.3.4

Pan Thomakos
  • 34,082
  • 9
  • 88
  • 85
Tom Lehman
  • 85,973
  • 71
  • 200
  • 272

1 Answers1

10

You'll have to do some Rails monkey-patching to do this. Be sure to only use this code in development and/or test though since you don't want your app raising errors if a user tries to mass-assign. I would add the following to config/initializers/error_mass_assign.rb:

module ActiveModel
  module MassAssignmentSecurity
    module Sanitizer
    protected
      def warn!(attrs)
        self.logger.debug "WARNING: Can't mass-assign protected attributes: #{attrs.join(', ')}" if self.logger
        raise(RuntimeError, "Mass assignment error") if ['test', 'development'].include?(Rails.env)
      end
    end
  end
end

This will raise the regular warning, but it will also raise a RuntimeError with the message "Mass assignment error" when in test and development environments anytime protected attributes are mass-assigned. You can also modify the error message or error in the code above if you prefer another exception.

Be sure to restart your console or server for this to take effect.

P.S: In Rails 2 you'll want to do the following:

module ActiveRecord
  class Base
    def log_protected_attribute_removal(*attributes)
      logger.debug "WARNING: Can't mass-assign these protected attributes: #{attributes.join(', ')}"
      raise(RuntimeError, "Mass assignment error")
    end
  end
end
Pan Thomakos
  • 34,082
  • 9
  • 88
  • 85
  • 1
    Why don't I want to do this in production? I.e., if a user tries to mass assign, he's either trying to do something that's against the rules (in which case it's fine if his request blows up) or I've forgotten to make an attribute accessible (in which case I want to know about it). – Tom Lehman Apr 05 '11 at 21:27
  • Also, and sorry for not mentioning in the question, but I'm using Rails 2.3.4. What changes should I make to your answer to get it to work in my version of Rails? – Tom Lehman Apr 05 '11 at 21:41
  • It's fine if you do, you'll just want to catch the error and handle it appropriately, you don't want to leave your user with 500 error pages and no explanation. For example, if the user is trying to hack your site then you should probably be notified when this happens, and if you have forgotten to set an attribute as accessible that is something you need to fix. – Pan Thomakos Apr 05 '11 at 21:43
  • 9
    Since Rails 3.2 you have this behavior by adding `config.active_record.mass_assignment_sanitizer = :strict` to your `development.rb` and `test.rb` config files – Florent2 Feb 14 '12 at 23:43
  • 1
    In newer Rails (3.2) Sanitizer is a class not a module – Robin Clowers Mar 10 '12 at 00:42