Skip to content
Browse files

Check attributes passed to create_with and where

If the request parameters are passed to create_with and where they can
be used to do mass assignment when used in combination with
Relation#create.

Fixes CVE-2014-3514

Conflicts:
	activerecord/lib/active_record/relation/query_methods.rb
  • Loading branch information...
1 parent e759b52 commit 306dc1a499908ba105e6b0fe8b8e01824c5e04d7 @rafaelfranca rafaelfranca committed Aug 6, 2014
View
1 activemodel/lib/active_model/forbidden_attributes_protection.rb
@@ -23,5 +23,6 @@ def sanitize_for_mass_assignment(attributes)
attributes
end
end
+ alias :sanitize_forbidden_attributes :sanitize_for_mass_assignment
end
end
View
16 activerecord/lib/active_record/relation/query_methods.rb
@@ -1,9 +1,12 @@
require 'active_support/core_ext/array/wrap'
+require 'active_model/forbidden_attributes_protection'
module ActiveRecord
module QueryMethods
extend ActiveSupport::Concern
+ include ActiveModel::ForbiddenAttributesProtection
+
# WhereChain objects act as placeholder for queries in which #where does not have any parameter.
# In this case, #where must be chained with #not to return a new relation.
class WhereChain
@@ -574,7 +577,10 @@ def where(opts = :chain, *rest)
end
def where!(opts, *rest) # :nodoc:
- references!(PredicateBuilder.references(opts)) if Hash === opts
+ if Hash === opts
+ opts = sanitize_forbidden_attributes(opts)
+ references!(PredicateBuilder.references(opts))
+ end
self.where_values += build_where(opts, rest)
self
@@ -723,7 +729,13 @@ def create_with(value)
end
def create_with!(value) # :nodoc:
- self.create_with_value = value ? create_with_value.merge(value) : {}
+ if value
+ value = sanitize_forbidden_attributes(value)
+ self.create_with_value = create_with_value.merge(value)
+ else
+ self.create_with_value = {}
+ end
+
self
end
View
30 activerecord/test/cases/forbidden_attributes_protection_test.rb
@@ -66,4 +66,34 @@ def test_blank_attributes_should_not_raise
person = Person.new
assert_nil person.assign_attributes(ProtectedParams.new({}))
end
+
+ def test_create_with_checks_permitted
+ params = ProtectedParams.new(first_name: 'Guille', gender: 'm')
+
+ assert_raises(ActiveModel::ForbiddenAttributesError) do
+ Person.create_with(params).create!
+ end
+ end
+
+ def test_create_with_works_with_params_values
+ params = ProtectedParams.new(first_name: 'Guille')
+
+ person = Person.create_with(first_name: params[:first_name]).create!
+ assert_equal 'Guille', person.first_name
+ end
+
+ def test_where_checks_permitted
+ params = ProtectedParams.new(first_name: 'Guille', gender: 'm')
+
+ assert_raises(ActiveModel::ForbiddenAttributesError) do
+ Person.where(params).create!
+ end
+ end
+
+ def test_where_works_with_params_values
+ params = ProtectedParams.new(first_name: 'Guille')
+
+ person = Person.where(first_name: params[:first_name]).create!
+ assert_equal 'Guille', person.first_name
+ end
end

0 comments on commit 306dc1a

Please sign in to comment.
Something went wrong with that request. Please try again.