From 0fde6f554b75b13b0435dd70f1c3ec02bc209e0d Mon Sep 17 00:00:00 2001 From: Andrew White Date: Fri, 27 Nov 2015 13:46:46 +0000 Subject: Don't short-circuit reject_if proc When updating an associated record via nested attribute hashes the reject_if proc could be bypassed if the _destroy flag was set in the attribute hash and allow_destroy was set to false. The fix is to only short-circuit if the _destroy flag is set and the option allow_destroy is set to true. It also fixes an issue where a new record wasn't created if _destroy was set and the option allow_destroy was set to false. CVE-2015-7577 --- activerecord/lib/active_record/nested_attributes.rb | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index c5a1488588..0d5a8e6f25 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -542,7 +542,7 @@ module ActiveRecord # has_destroy_flag? or if a :reject_if proc exists for this # association and evaluates to +true+. def reject_new_record?(association_name, attributes) - has_destroy_flag?(attributes) || call_reject_if(association_name, attributes) + will_be_destroyed?(association_name, attributes) || call_reject_if(association_name, attributes) end # Determines if a record with the particular +attributes+ should be @@ -551,7 +551,8 @@ module ActiveRecord # # Returns false if there is a +destroy_flag+ on the attributes. def call_reject_if(association_name, attributes) - return false if has_destroy_flag?(attributes) + return false if will_be_destroyed?(association_name, attributes) + case callback = self.nested_attributes_options[association_name][:reject_if] when Symbol method(callback).arity == 0 ? send(callback) : send(callback, attributes) @@ -560,6 +561,15 @@ module ActiveRecord end end + # Only take into account the destroy flag if :allow_destroy is true + def will_be_destroyed?(association_name, attributes) + allow_destroy?(association_name) && has_destroy_flag?(attributes) + end + + def allow_destroy?(association_name) + self.nested_attributes_options[association_name][:allow_destroy] + end + def raise_nested_attributes_record_not_found!(association_name, record_id) model = self.class._reflect_on_association(association_name).klass.name raise RecordNotFound.new("Couldn't find #{model} with ID=#{record_id} for #{self.class.name} with ID=#{id}", -- cgit v1.2.3 From 4642d68d8021893c69bfd16ed6e926ae03a6d777 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 18 Jan 2016 13:51:02 -0800 Subject: Eliminate instance level writers for class accessors Instance level writers can have an impact on how the Active Model / Record objects are saved. Specifically, they can be used to bypass validations. This is a problem if mass assignment protection is disabled and specific attributes are passed to the constructor. CVE-2016-0753 --- activerecord/lib/active_record/enum.rb | 2 +- activerecord/lib/active_record/reflection.rb | 4 ++-- activerecord/lib/active_record/scoping/default.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/enum.rb b/activerecord/lib/active_record/enum.rb index 7ded96f8fb..610b863794 100644 --- a/activerecord/lib/active_record/enum.rb +++ b/activerecord/lib/active_record/enum.rb @@ -95,7 +95,7 @@ module ActiveRecord module Enum def self.extended(base) # :nodoc: - base.class_attribute(:defined_enums) + base.class_attribute(:defined_enums, instance_writer: false) base.defined_enums = {} end diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index a549b28f16..27b9d0754b 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -7,8 +7,8 @@ module ActiveRecord extend ActiveSupport::Concern included do - class_attribute :_reflections - class_attribute :aggregate_reflections + class_attribute :_reflections, instance_writer: false + class_attribute :aggregate_reflections, instance_writer: false self._reflections = {} self.aggregate_reflections = {} end diff --git a/activerecord/lib/active_record/scoping/default.rb b/activerecord/lib/active_record/scoping/default.rb index cdcb73382f..c9f689ee17 100644 --- a/activerecord/lib/active_record/scoping/default.rb +++ b/activerecord/lib/active_record/scoping/default.rb @@ -6,7 +6,7 @@ module ActiveRecord included do # Stores the default scope for the class. class_attribute :default_scopes, instance_writer: false, instance_predicate: false - class_attribute :default_scope_override, instance_predicate: false + class_attribute :default_scope_override, instance_writer: false, instance_predicate: false self.default_scopes = [] self.default_scope_override = nil -- cgit v1.2.3 From 908c011395cc9e3ea1bb195f9d1bd30a9d9df98f Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 25 Jan 2016 10:22:15 -0800 Subject: bumping version --- activerecord/lib/active_record/gem_version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/gem_version.rb b/activerecord/lib/active_record/gem_version.rb index ecf4046bff..b4f2f66e1c 100644 --- a/activerecord/lib/active_record/gem_version.rb +++ b/activerecord/lib/active_record/gem_version.rb @@ -8,7 +8,7 @@ module ActiveRecord MAJOR = 5 MINOR = 0 TINY = 0 - PRE = "beta1" + PRE = "beta1.1" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end -- cgit v1.2.3