Skip to content

Commit 306dc1a

Browse files
committed
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
1 parent e759b52 commit 306dc1a

File tree

3 files changed

+45
-2
lines changed

3 files changed

+45
-2
lines changed

activemodel/lib/active_model/forbidden_attributes_protection.rb

+1
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,6 @@ def sanitize_for_mass_assignment(attributes)
2323
attributes
2424
end
2525
end
26+
alias :sanitize_forbidden_attributes :sanitize_for_mass_assignment
2627
end
2728
end

activerecord/lib/active_record/relation/query_methods.rb

+14-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
require 'active_support/core_ext/array/wrap'
2+
require 'active_model/forbidden_attributes_protection'
23

34
module ActiveRecord
45
module QueryMethods
56
extend ActiveSupport::Concern
67

8+
include ActiveModel::ForbiddenAttributesProtection
9+
710
# WhereChain objects act as placeholder for queries in which #where does not have any parameter.
811
# In this case, #where must be chained with #not to return a new relation.
912
class WhereChain
@@ -574,7 +577,10 @@ def where(opts = :chain, *rest)
574577
end
575578

576579
def where!(opts, *rest) # :nodoc:
577-
references!(PredicateBuilder.references(opts)) if Hash === opts
580+
if Hash === opts
581+
opts = sanitize_forbidden_attributes(opts)
582+
references!(PredicateBuilder.references(opts))
583+
end
578584

579585
self.where_values += build_where(opts, rest)
580586
self
@@ -723,7 +729,13 @@ def create_with(value)
723729
end
724730

725731
def create_with!(value) # :nodoc:
726-
self.create_with_value = value ? create_with_value.merge(value) : {}
732+
if value
733+
value = sanitize_forbidden_attributes(value)
734+
self.create_with_value = create_with_value.merge(value)
735+
else
736+
self.create_with_value = {}
737+
end
738+
727739
self
728740
end
729741

activerecord/test/cases/forbidden_attributes_protection_test.rb

+30
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,34 @@ def test_blank_attributes_should_not_raise
6666
person = Person.new
6767
assert_nil person.assign_attributes(ProtectedParams.new({}))
6868
end
69+
70+
def test_create_with_checks_permitted
71+
params = ProtectedParams.new(first_name: 'Guille', gender: 'm')
72+
73+
assert_raises(ActiveModel::ForbiddenAttributesError) do
74+
Person.create_with(params).create!
75+
end
76+
end
77+
78+
def test_create_with_works_with_params_values
79+
params = ProtectedParams.new(first_name: 'Guille')
80+
81+
person = Person.create_with(first_name: params[:first_name]).create!
82+
assert_equal 'Guille', person.first_name
83+
end
84+
85+
def test_where_checks_permitted
86+
params = ProtectedParams.new(first_name: 'Guille', gender: 'm')
87+
88+
assert_raises(ActiveModel::ForbiddenAttributesError) do
89+
Person.where(params).create!
90+
end
91+
end
92+
93+
def test_where_works_with_params_values
94+
params = ProtectedParams.new(first_name: 'Guille')
95+
96+
person = Person.where(first_name: params[:first_name]).create!
97+
assert_equal 'Guille', person.first_name
98+
end
6999
end

0 commit comments

Comments
 (0)