[DRE-commits] [rails] 01/02: Several security updates
Antonio Terceiro
terceiro at moszumanska.debian.org
Thu Jan 28 19:04:52 UTC 2016
This is an automated email from the git hooks/post-receive script.
terceiro pushed a commit to branch debian/jessie
in repository rails.
commit 5cb92f0df4467e6589c25ec6bfe5a745b51ee7c1
Author: Antonio Terceiro <terceiro at debian.org>
Date: Thu Jan 28 11:16:13 2016 -0200
Several security updates
---
debian/changelog | 17 +++
debian/patches/CVE-2015-3226.patch | 48 +++++++
debian/patches/CVE-2015-3227.patch | 113 +++++++++++++++
debian/patches/CVE-2015-7576.patch | 77 ++++++++++
debian/patches/CVE-2015-7577.patch | 86 +++++++++++
debian/patches/CVE-2015-7581.patch | 52 +++++++
debian/patches/CVE-2016-0751.patch | 76 ++++++++++
debian/patches/CVE-2016-0752.patch | 285 +++++++++++++++++++++++++++++++++++++
debian/patches/CVE-2016-0753.patch | 83 +++++++++++
debian/patches/series | 8 ++
10 files changed, 845 insertions(+)
diff --git a/debian/changelog b/debian/changelog
index ff85cf3..7707d19 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,20 @@
+rails (2:4.1.8-1+deb8u1) jessie-security; urgency=high
+
+ * Security updates:
+ - [CVE-2015-3227] Possible Denial of Service attack in Active Support
+ - [CVE-2015-3226] XSS Vulnerability in ActiveSupport::JSON.encode
+ - [CVE-2015-7576] Timing attack vulnerability in basic authentication in
+ Action Controller.
+ - [CVE-2016-0751] Possible Object Leak and Denial of Service attack in
+ Action Pack
+ - [CVE-2015-7577] Nested attributes rejection proc bypass in Active Record.
+ - [CVE-2016-0752] Possible Information Leak Vulnerability in Action View
+ - [CVE-2016-0753] Possible Input Validation Circumvention in Active Model
+ - [CVE-2015-7581] Object leak vulnerability for wildcard controller routes
+ in Action Pack
+
+ -- Antonio Terceiro <terceiro at debian.org> Thu, 28 Jan 2016 11:12:33 -0200
+
rails (2:4.1.8-1) unstable; urgency=medium
* New upstream release
diff --git a/debian/patches/CVE-2015-3226.patch b/debian/patches/CVE-2015-3226.patch
new file mode 100644
index 0000000..9f5347d
--- /dev/null
+++ b/debian/patches/CVE-2015-3226.patch
@@ -0,0 +1,48 @@
+From bfbf16749a754ab1fd58274a951d3a013182a635 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?=
+ <rafaelmfranca at gmail.com>
+Date: Mon, 15 Jun 2015 15:23:01 -0300
+Subject: [PATCH] Escape HTML entities in JSON keys
+
+Fixes CVE-2015-3226
+---
+ activesupport/lib/active_support/json/encoding.rb | 4 ++++
+ activesupport/test/json/encoding_test.rb | 7 +++++++
+ 2 files changed, 11 insertions(+)
+
+diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb
+index f29d422..d0f67b1 100644
+--- a/activesupport/lib/active_support/json/encoding.rb
++++ b/activesupport/lib/active_support/json/encoding.rb
+@@ -58,6 +58,10 @@ module ActiveSupport
+ super.gsub ESCAPE_REGEX_WITHOUT_HTML_ENTITIES, ESCAPED_CHARS
+ end
+ end
++
++ def to_s
++ self
++ end
+ end
+
+ # Mark these as private so we don't leak encoding-specific constructs
+diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb
+index c4283ee..b75c67c 100644
+--- a/activesupport/test/json/encoding_test.rb
++++ b/activesupport/test/json/encoding_test.rb
+@@ -143,6 +143,13 @@ class TestJSONEncoding < ActiveSupport::TestCase
+ assert_equal %({\"a\":\"b\",\"c\":\"d\"}), sorted_json(ActiveSupport::JSON.encode(:a => :b, :c => :d))
+ end
+
++ def test_hash_keys_encoding
++ ActiveSupport.escape_html_entities_in_json = true
++ assert_equal "{\"\\u003c\\u003e\":\"\\u003c\\u003e\"}", ActiveSupport::JSON.encode("<>" => "<>")
++ ensure
++ ActiveSupport.escape_html_entities_in_json = false
++ end
++
+ def test_utf8_string_encoded_properly
+ result = ActiveSupport::JSON.encode('€2.99')
+ assert_equal '"€2.99"', result
+--
+2.4.0
+
diff --git a/debian/patches/CVE-2015-3227.patch b/debian/patches/CVE-2015-3227.patch
new file mode 100644
index 0000000..d8a4084
--- /dev/null
+++ b/debian/patches/CVE-2015-3227.patch
@@ -0,0 +1,113 @@
+From eb4f1d6a02e9557b97cdbed76157dc5a625cdb82 Mon Sep 17 00:00:00 2001
+From: Aaron Patterson <aaron.patterson at gmail.com>
+Date: Tue, 9 Jun 2015 11:24:25 -0700
+Subject: [PATCH] enforce a depth limit on XML documents
+
+XML documents that are too deep can cause an stack overflow, which in
+turn will cause a potential DoS attack.
+
+CVE-2015-3227
+---
+ activesupport/lib/active_support/xml_mini.rb | 3 +++
+ activesupport/lib/active_support/xml_mini/jdom.rb | 11 ++++++-----
+ activesupport/lib/active_support/xml_mini/rexml.rb | 11 ++++++-----
+ 3 files changed, 15 insertions(+), 10 deletions(-)
+
+diff --git a/activesupport/lib/active_support/xml_mini.rb b/activesupport/lib/active_support/xml_mini.rb
+index 009ee4d..df7b081 100644
+--- a/activesupport/lib/active_support/xml_mini.rb
++++ b/activesupport/lib/active_support/xml_mini.rb
+@@ -78,6 +78,9 @@ module ActiveSupport
+ )
+ end
+
++ attr_accessor :depth
++ self.depth = 100
++
+ delegate :parse, :to => :backend
+
+ def backend
+diff --git a/activesupport/lib/active_support/xml_mini/jdom.rb b/activesupport/lib/active_support/xml_mini/jdom.rb
+index 27c64c4..cdc5490 100644
+--- a/activesupport/lib/active_support/xml_mini/jdom.rb
++++ b/activesupport/lib/active_support/xml_mini/jdom.rb
+@@ -46,7 +46,7 @@ module ActiveSupport
+ xml_string_reader = StringReader.new(data)
+ xml_input_source = InputSource.new(xml_string_reader)
+ doc = @dbf.new_document_builder.parse(xml_input_source)
+- merge_element!({CONTENT_KEY => ''}, doc.document_element)
++ merge_element!({CONTENT_KEY => ''}, doc.document_element, XmlMini.depth)
+ end
+ end
+
+@@ -58,9 +58,10 @@ module ActiveSupport
+ # Hash to merge the converted element into.
+ # element::
+ # XML element to merge into hash
+- def merge_element!(hash, element)
++ def merge_element!(hash, element, depth)
++ raise 'Document too deep!' if depth == 0
+ delete_empty(hash)
+- merge!(hash, element.tag_name, collapse(element))
++ merge!(hash, element.tag_name, collapse(element, depth))
+ end
+
+ def delete_empty(hash)
+@@ -71,14 +72,14 @@ module ActiveSupport
+ #
+ # element::
+ # The document element to be collapsed.
+- def collapse(element)
++ def collapse(element, depth)
+ hash = get_attributes(element)
+
+ child_nodes = element.child_nodes
+ if child_nodes.length > 0
+ (0...child_nodes.length).each do |i|
+ child = child_nodes.item(i)
+- merge_element!(hash, child) unless child.node_type == Node.TEXT_NODE
++ merge_element!(hash, child, depth - 1) unless child.node_type == Node.TEXT_NODE
+ end
+ merge_texts!(hash, element) unless empty_content?(element)
+ hash
+diff --git a/activesupport/lib/active_support/xml_mini/rexml.rb b/activesupport/lib/active_support/xml_mini/rexml.rb
+index 5c7c78b..924ed72 100644
+--- a/activesupport/lib/active_support/xml_mini/rexml.rb
++++ b/activesupport/lib/active_support/xml_mini/rexml.rb
+@@ -29,7 +29,7 @@ module ActiveSupport
+ doc = REXML::Document.new(data)
+
+ if doc.root
+- merge_element!({}, doc.root)
++ merge_element!({}, doc.root, XmlMini.depth)
+ else
+ raise REXML::ParseException,
+ "The document #{doc.to_s.inspect} does not have a valid root"
+@@ -44,19 +44,20 @@ module ActiveSupport
+ # Hash to merge the converted element into.
+ # element::
+ # XML element to merge into hash
+- def merge_element!(hash, element)
+- merge!(hash, element.name, collapse(element))
++ def merge_element!(hash, element, depth)
++ raise REXML::ParseException, "The document is too deep" if depth == 0
++ merge!(hash, element.name, collapse(element, depth))
+ end
+
+ # Actually converts an XML document element into a data structure.
+ #
+ # element::
+ # The document element to be collapsed.
+- def collapse(element)
++ def collapse(element, depth)
+ hash = get_attributes(element)
+
+ if element.has_elements?
+- element.each_element {|child| merge_element!(hash, child) }
++ element.each_element {|child| merge_element!(hash, child, depth - 1) }
+ merge_texts!(hash, element) unless empty_content?(element)
+ hash
+ else
+--
+2.2.1
+
diff --git a/debian/patches/CVE-2015-7576.patch b/debian/patches/CVE-2015-7576.patch
new file mode 100644
index 0000000..d388b0e
--- /dev/null
+++ b/debian/patches/CVE-2015-7576.patch
@@ -0,0 +1,77 @@
+From 0de876c53fe9355f1e9a73e923519f2a2241f527 Mon Sep 17 00:00:00 2001
+From: Aaron Patterson <aaron.patterson at gmail.com>
+Date: Thu, 29 Oct 2015 10:42:44 -0700
+Subject: [PATCH] use secure string comparisons for basic auth username /
+ password
+
+this will avoid timing attacks against applications that use basic auth.
+
+Conflicts:
+ activesupport/lib/active_support/security_utils.rb
+
+CVE-2015-7576
+---
+ .../action_controller/metal/http_authentication.rb | 7 +++++-
+ activesupport/lib/active_support/security_utils.rb | 27 ++++++++++++++++++++++
+ 2 files changed, 33 insertions(+), 1 deletion(-)
+ create mode 100644 activesupport/lib/active_support/security_utils.rb
+
+diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
+index 167df2f..db93e20 100644
+--- a/actionpack/lib/action_controller/metal/http_authentication.rb
++++ b/actionpack/lib/action_controller/metal/http_authentication.rb
+@@ -1,4 +1,5 @@
+ require 'base64'
++require 'active_support/security_utils'
+
+ module ActionController
+ # Makes it dead easy to do HTTP Basic, Digest and Token authentication.
+@@ -70,7 +71,11 @@ module ActionController
+ def http_basic_authenticate_with(options = {})
+ before_action(options.except(:name, :password, :realm)) do
+ authenticate_or_request_with_http_basic(options[:realm] || "Application") do |name, password|
+- name == options[:name] && password == options[:password]
++ # This comparison uses & so that it doesn't short circuit and
++ # uses `variable_size_secure_compare` so that length information
++ # isn't leaked.
++ ActiveSupport::SecurityUtils.variable_size_secure_compare(name, options[:name]) &
++ ActiveSupport::SecurityUtils.variable_size_secure_compare(password, options[:password])
+ end
+ end
+ end
+diff --git a/activesupport/lib/active_support/security_utils.rb b/activesupport/lib/active_support/security_utils.rb
+new file mode 100644
+index 0000000..bb22125
+--- /dev/null
++++ b/activesupport/lib/active_support/security_utils.rb
+@@ -0,0 +1,27 @@
++require 'digest'
++
++module ActiveSupport
++ module SecurityUtils
++ # Constant time string comparison.
++ #
++ # The values compared should be of fixed length, such as strings
++ # that have already been processed by HMAC. This should not be used
++ # on variable length plaintext strings because it could leak length info
++ # via timing attacks.
++ def secure_compare(a, b)
++ return false unless a.bytesize == b.bytesize
++
++ l = a.unpack "C#{a.bytesize}"
++
++ res = 0
++ b.each_byte { |byte| res |= byte ^ l.shift }
++ res == 0
++ end
++ module_function :secure_compare
++
++ def variable_size_secure_compare(a, b) # :nodoc:
++ secure_compare(::Digest::SHA256.hexdigest(a), ::Digest::SHA256.hexdigest(b))
++ end
++ module_function :variable_size_secure_compare
++ end
++end
+--
+2.2.1
+
diff --git a/debian/patches/CVE-2015-7577.patch b/debian/patches/CVE-2015-7577.patch
new file mode 100644
index 0000000..cc667c1
--- /dev/null
+++ b/debian/patches/CVE-2015-7577.patch
@@ -0,0 +1,86 @@
+From 5dc869dc73bcbe0b3dd415f257cf175015c4d014 Mon Sep 17 00:00:00 2001
+From: Andrew White <andyw at pixeltrix.co.uk>
+Date: Fri, 27 Nov 2015 13:46:46 +0000
+Subject: [PATCH] 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 ++++++++++++--
+ activerecord/test/cases/nested_attributes_test.rb | 13 +++++++++++++
+ 2 files changed, 25 insertions(+), 2 deletions(-)
+
+diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb
+index 6df01b7..03a4009 100644
+--- a/activerecord/lib/active_record/nested_attributes.rb
++++ b/activerecord/lib/active_record/nested_attributes.rb
+@@ -523,7 +523,7 @@ module ActiveRecord
+ # has_destroy_flag? or if a <tt>:reject_if</tt> 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
+@@ -532,7 +532,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)
+@@ -541,6 +542,15 @@ module ActiveRecord
+ end
+ end
+
++ # Only take into account the destroy flag if <tt>:allow_destroy</tt> 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)
+ raise RecordNotFound, "Couldn't find #{self.class._reflect_on_association(association_name).klass.name} with ID=#{record_id} for #{self.class.name} with ID=#{id}"
+ end
+diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb
+index c87a837..e421600 100644
+--- a/activerecord/test/cases/nested_attributes_test.rb
++++ b/activerecord/test/cases/nested_attributes_test.rb
+@@ -161,6 +161,19 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase
+ assert man.reload.interests.empty?
+ end
+
++ def test_reject_if_is_not_short_circuited_if_allow_destroy_is_false
++ Pirate.accepts_nested_attributes_for :ship, reject_if: ->(a) { a[:name] == "The Golden Hind" }, allow_destroy: false
++
++ pirate = Pirate.create!(catchphrase: "Stop wastin' me time", ship_attributes: { name: "White Pearl", _destroy: "1" })
++ assert_equal "White Pearl", pirate.reload.ship.name
++
++ pirate.update!(ship_attributes: { id: pirate.ship.id, name: "The Golden Hind", _destroy: "1" })
++ assert_equal "White Pearl", pirate.reload.ship.name
++
++ pirate.update!(ship_attributes: { id: pirate.ship.id, name: "Black Pearl", _destroy: "1" })
++ assert_equal "Black Pearl", pirate.reload.ship.name
++ end
++
+ def test_has_many_association_updating_a_single_record
+ Man.accepts_nested_attributes_for(:interests)
+ man = Man.create(name: 'John')
+--
+2.4.9 (Apple Git-60)
+
diff --git a/debian/patches/CVE-2015-7581.patch b/debian/patches/CVE-2015-7581.patch
new file mode 100644
index 0000000..096a6a5
--- /dev/null
+++ b/debian/patches/CVE-2015-7581.patch
@@ -0,0 +1,52 @@
+From fb790341d0ea25ad91116c283d49a2c83a8ea299 Mon Sep 17 00:00:00 2001
+From: eileencodes <eileencodes at gmail.com>
+Date: Fri, 21 Aug 2015 11:26:19 -0400
+Subject: [PATCH] Remove unnecessary caching
+
+`ActiveSupport::Dependencies.constantize(const_name)` calls
+`Reference.new` which is defined as
+`ActiveSupport::Dependencies.constantize(const_name)` meaning this call
+is already cached and we're doing caching that isn't necessary.
+
+Conflicts:
+ actionpack/lib/action_dispatch/routing/route_set.rb
+
+Conflicts:
+ actionpack/lib/action_dispatch/routing/route_set.rb
+
+CVE-2015-7581
+---
+ actionpack/lib/action_dispatch/routing/route_set.rb | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
+index 51dd607..5f727fd 100644
+--- a/actionpack/lib/action_dispatch/routing/route_set.rb
++++ b/actionpack/lib/action_dispatch/routing/route_set.rb
+@@ -1,6 +1,5 @@
+ require 'action_dispatch/journey'
+ require 'forwardable'
+-require 'thread_safe'
+ require 'active_support/concern'
+ require 'active_support/core_ext/object/to_query'
+ require 'active_support/core_ext/hash/slice'
+@@ -24,7 +23,6 @@ module ActionDispatch
+ def initialize(options={})
+ @defaults = options[:defaults]
+ @glob_param = options.delete(:glob)
+- @controller_class_names = ThreadSafe::Cache.new
+ end
+
+ def call(env)
+@@ -74,7 +72,7 @@ module ActionDispatch
+ private
+
+ def controller_reference(controller_param)
+- const_name = @controller_class_names[controller_param] ||= "#{controller_param.camelize}Controller"
++ const_name = "#{controller_param.camelize}Controller"
+ ActiveSupport::Dependencies.constantize(const_name)
+ end
+
+--
+2.2.1
+
diff --git a/debian/patches/CVE-2016-0751.patch b/debian/patches/CVE-2016-0751.patch
new file mode 100644
index 0000000..725f605
--- /dev/null
+++ b/debian/patches/CVE-2016-0751.patch
@@ -0,0 +1,76 @@
+From 5756321cd9e3ca12cb2b8402704c6680b4d7ca2a Mon Sep 17 00:00:00 2001
+From: Aaron Patterson <aaron.patterson at gmail.com>
+Date: Mon, 11 Jan 2016 14:36:49 -0800
+Subject: [PATCH] stop caching mime types globally
+
+Unknown mime types should not be cached globally. This global cache
+leads to a memory leak and a denial of service vulnerability.
+
+CVE-2016-0751
+---
+ actionpack/lib/action_dispatch/http/mime_type.rb | 18 ++++++++++++++++--
+ 1 file changed, 16 insertions(+), 2 deletions(-)
+
+diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb
+index 9450be8..fc986f9 100644
+--- a/actionpack/lib/action_dispatch/http/mime_type.rb
++++ b/actionpack/lib/action_dispatch/http/mime_type.rb
+@@ -23,7 +23,7 @@ module Mime
+
+ SET = Mimes.new
+ EXTENSION_LOOKUP = {}
+- LOOKUP = Hash.new { |h, k| h[k] = Type.new(k) unless k.blank? }
++ LOOKUP = {}
+
+ class << self
+ def [](type)
+@@ -146,7 +146,7 @@ module Mime
+ end
+
+ def lookup(string)
+- LOOKUP[string]
++ LOOKUP[string] || Type.new(string)
+ end
+
+ def lookup_by_extension(extension)
+@@ -225,9 +225,12 @@ module Mime
+ end
+ end
+
++ attr_reader :hash
++
+ def initialize(string, symbol = nil, synonyms = [])
+ @symbol, @synonyms = symbol, synonyms
+ @string = string
++ @hash = [@string, @synonyms, @symbol].hash
+ end
+
+ def to_s
+@@ -261,6 +264,13 @@ module Mime
+ end
+ end
+
++ def eql?(other)
++ super || (self.class == other.class &&
++ @string == other.string &&
++ @synonyms == other.synonyms &&
++ @symbol == other.symbol)
++ end
++
+ def =~(mime_type)
+ return false if mime_type.blank?
+ regexp = Regexp.new(Regexp.quote(mime_type.to_s))
+@@ -274,6 +284,10 @@ module Mime
+ end
+
+
++ protected
++
++ attr_reader :string, :synonyms
++
+ private
+
+ def to_ary; end
+--
+2.2.1
+
diff --git a/debian/patches/CVE-2016-0752.patch b/debian/patches/CVE-2016-0752.patch
new file mode 100644
index 0000000..96a8804
--- /dev/null
+++ b/debian/patches/CVE-2016-0752.patch
@@ -0,0 +1,285 @@
+From 5c656a271a890cca4b3d438cc1fc76ff98011cbe Mon Sep 17 00:00:00 2001
+From: Aaron Patterson <aaron.patterson at gmail.com>
+Date: Wed, 20 Jan 2016 10:39:19 -0800
+Subject: [PATCH] allow :file to be outside rails root, but anything else must
+ be inside the rails view directory
+
+Conflicts:
+ actionpack/test/controller/render_test.rb
+ actionview/lib/action_view/template/resolver.rb
+
+CVE-2016-0752
+---
+ actionpack/lib/abstract_controller/rendering.rb | 8 +++++-
+ actionpack/test/controller/render_test.rb | 31 ++++++++++++++++++++++
+ actionview/lib/action_view/lookup_context.rb | 4 +++
+ actionview/lib/action_view/path_set.rb | 26 +++++++++++++-----
+ .../lib/action_view/renderer/abstract_renderer.rb | 2 +-
+ .../lib/action_view/renderer/template_renderer.rb | 2 +-
+ actionview/lib/action_view/template/resolver.rb | 25 ++++++++++++++---
+ actionview/lib/action_view/testing/resolvers.rb | 4 +--
+ actionview/test/template/render_test.rb | 7 +++++
+ 9 files changed, 93 insertions(+), 16 deletions(-)
+
+diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb
+index 9d10140..e80d97f 100644
+--- a/actionpack/lib/abstract_controller/rendering.rb
++++ b/actionpack/lib/abstract_controller/rendering.rb
+@@ -77,7 +77,13 @@ module AbstractController
+ # render "foo/bar" to render :file => "foo/bar".
+ # :api: plugin
+ def _normalize_args(action=nil, options={})
+- if action.is_a? Hash
++ case action
++ when ActionController::Parameters
++ unless action.permitted?
++ raise ArgumentError, "render parameters are not permitted"
++ end
++ action
++ when Hash
+ action
+ else
+ options
+diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
+index 26806fb..17a019e 100644
+--- a/actionpack/test/controller/render_test.rb
++++ b/actionpack/test/controller/render_test.rb
+@@ -52,6 +52,16 @@ class TestController < ActionController::Base
+ end
+ end
+
++ def dynamic_render
++ render params[:id] # => String, AC:Params
++ end
++
++ def dynamic_render_with_file
++ # This is extremely bad, but should be possible to do.
++ file = params[:id] # => String, AC:Params
++ render file: file
++ end
++
+ def conditional_hello_with_public_header
+ if stale?(:last_modified => Time.now.utc.beginning_of_day, :etag => [:foo, 123], :public => true)
+ render :action => 'hello_world'
+@@ -251,6 +261,27 @@ end
+ class ExpiresInRenderTest < ActionController::TestCase
+ tests TestController
+
++ def test_dynamic_render_with_file
++ # This is extremely bad, but should be possible to do.
++ assert File.exist?(File.join(File.dirname(__FILE__), '../../test/abstract_unit.rb'))
++ response = get :dynamic_render_with_file, { id: '../\\../test/abstract_unit.rb' }
++ assert_equal File.read(File.join(File.dirname(__FILE__), '../../test/abstract_unit.rb')),
++ response.body
++ end
++
++ def test_dynamic_render
++ assert File.exist?(File.join(File.dirname(__FILE__), '../../test/abstract_unit.rb'))
++ assert_raises ActionView::MissingTemplate do
++ get :dynamic_render, { id: '../\\../test/abstract_unit.rb' }
++ end
++ end
++
++ def test_dynamic_render_file_hash
++ assert_raises ArgumentError do
++ get :dynamic_render, { id: { file: '../\\../test/abstract_unit.rb' } }
++ end
++ end
++
+ def test_expires_in_header
+ get :conditional_hello_with_expires_in
+ assert_equal "max-age=60, private", @response.headers["Cache-Control"]
+diff --git a/actionview/lib/action_view/lookup_context.rb b/actionview/lib/action_view/lookup_context.rb
+index 855fed0..93ef701 100644
+--- a/actionview/lib/action_view/lookup_context.rb
++++ b/actionview/lib/action_view/lookup_context.rb
+@@ -125,6 +125,10 @@ module ActionView
+ end
+ alias :find_template :find
+
++ def find_file(name, prefixes = [], partial = false, keys = [], options = {})
++ @view_paths.find_file(*args_for_lookup(name, prefixes, partial, keys, options))
++ end
++
+ def find_all(name, prefixes = [], partial = false, keys = [], options = {})
+ @view_paths.find_all(*args_for_lookup(name, prefixes, partial, keys, options))
+ end
+diff --git a/actionview/lib/action_view/path_set.rb b/actionview/lib/action_view/path_set.rb
+index 91ee2ea..8d21913 100644
+--- a/actionview/lib/action_view/path_set.rb
++++ b/actionview/lib/action_view/path_set.rb
+@@ -46,23 +46,35 @@ module ActionView #:nodoc:
+ find_all(*args).first || raise(MissingTemplate.new(self, *args))
+ end
+
++ def find_file(path, prefixes = [], *args)
++ _find_all(path, prefixes, args, true).first || raise(MissingTemplate.new(self, path, prefixes, *args))
++ end
++
+ def find_all(path, prefixes = [], *args)
++ _find_all path, prefixes, args, false
++ end
++
++ def exists?(path, prefixes, *args)
++ find_all(path, prefixes, *args).any?
++ end
++
++ private
++
++ def _find_all(path, prefixes, args, outside_app)
+ prefixes = [prefixes] if String === prefixes
+ prefixes.each do |prefix|
+ paths.each do |resolver|
+- templates = resolver.find_all(path, prefix, *args)
++ if outside_app
++ templates = resolver.find_all_anywhere(path, prefix, *args)
++ else
++ templates = resolver.find_all(path, prefix, *args)
++ end
+ return templates unless templates.empty?
+ end
+ end
+ []
+ end
+
+- def exists?(path, prefixes, *args)
+- find_all(path, prefixes, *args).any?
+- end
+-
+- private
+-
+ def typecast(paths)
+ paths.map do |path|
+ case path
+diff --git a/actionview/lib/action_view/renderer/abstract_renderer.rb b/actionview/lib/action_view/renderer/abstract_renderer.rb
+index 73c19a0..8457008 100644
+--- a/actionview/lib/action_view/renderer/abstract_renderer.rb
++++ b/actionview/lib/action_view/renderer/abstract_renderer.rb
+@@ -15,7 +15,7 @@ module ActionView
+ # that new object is called in turn. This abstracts the setup and rendering
+ # into a separate classes for partials and templates.
+ class AbstractRenderer #:nodoc:
+- delegate :find_template, :template_exists?, :with_fallbacks, :with_layout_format, :formats, :to => :@lookup_context
++ delegate :find_template, :find_file, :template_exists?, :with_fallbacks, :with_layout_format, :formats, :to => :@lookup_context
+
+ def initialize(lookup_context)
+ @lookup_context = lookup_context
+diff --git a/actionview/lib/action_view/renderer/template_renderer.rb b/actionview/lib/action_view/renderer/template_renderer.rb
+index be17097..66b611d 100644
+--- a/actionview/lib/action_view/renderer/template_renderer.rb
++++ b/actionview/lib/action_view/renderer/template_renderer.rb
+@@ -30,7 +30,7 @@ module ActionView
+ elsif options.key?(:html)
+ Template::HTML.new(options[:html], formats.first)
+ elsif options.key?(:file)
+- with_fallbacks { find_template(options[:file], nil, false, keys, @details) }
++ with_fallbacks { find_file(options[:file], nil, false, keys, @details) }
+ elsif options.key?(:inline)
+ handler = Template.handler_for_extension(options[:type] || "erb")
+ Template.new(options[:inline], "inline template", handler, :locals => keys)
+diff --git a/actionview/lib/action_view/template/resolver.rb b/actionview/lib/action_view/template/resolver.rb
+index f1bb47a..8d8a37e 100644
+--- a/actionview/lib/action_view/template/resolver.rb
++++ b/actionview/lib/action_view/template/resolver.rb
+@@ -112,7 +112,13 @@ module ActionView
+ # Normalizes the arguments and passes it on to find_templates.
+ def find_all(name, prefix=nil, partial=false, details={}, key=nil, locals=[])
+ cached(key, [name, prefix, partial], details, locals) do
+- find_templates(name, prefix, partial, details)
++ find_templates(name, prefix, partial, details, false)
++ end
++ end
++
++ def find_all_anywhere(name, prefix, partial=false, details={}, key=nil, locals=[])
++ cached(key, [name, prefix, partial], details, locals) do
++ find_templates(name, prefix, partial, details, true)
+ end
+ end
+
+@@ -173,15 +179,16 @@ module ActionView
+
+ private
+
+- def find_templates(name, prefix, partial, details)
++ def find_templates(name, prefix, partial, details, outside_app_allowed = false)
+ path = Path.build(name, prefix, partial)
+- query(path, details, details[:formats])
++ query(path, details, details[:formats], outside_app_allowed)
+ end
+
+- def query(path, details, formats)
++ def query(path, details, formats, outside_app_allowed)
+ query = build_query(path, details)
+
+ template_paths = find_template_paths query
++ template_paths = reject_files_external_to_app(template_paths) unless outside_app_allowed
+
+ template_paths.map { |template|
+ handler, format, variant = extract_handler_and_format_and_variant(template, formats)
+@@ -196,6 +203,10 @@ module ActionView
+ }
+ end
+
++ def reject_files_external_to_app(files)
++ files.reject { |filename| !inside_path?(@path, filename) }
++ end
++
+ if RUBY_VERSION >= '2.2.0'
+ def find_template_paths(query)
+ Dir[query].reject { |filename|
+@@ -216,6 +227,12 @@ module ActionView
+ end
+ end
+
++ def inside_path?(path, filename)
++ filename = File.expand_path(filename)
++ path = File.join(path, '')
++ filename.start_with?(path)
++ end
++
+ # Helper for building query glob string based on resolver's pattern.
+ def build_query(path, details)
+ query = @pattern.dup
+diff --git a/actionview/lib/action_view/testing/resolvers.rb b/actionview/lib/action_view/testing/resolvers.rb
+index dfb7d46..e88f425 100644
+--- a/actionview/lib/action_view/testing/resolvers.rb
++++ b/actionview/lib/action_view/testing/resolvers.rb
+@@ -19,7 +19,7 @@ module ActionView #:nodoc:
+
+ private
+
+- def query(path, exts, formats)
++ def query(path, exts, formats, _)
+ query = ""
+ EXTENSIONS.each_key do |ext|
+ query << '(' << exts[ext].map {|e| e && Regexp.escape(".#{e}") }.join('|') << '|)'
+@@ -44,7 +44,7 @@ module ActionView #:nodoc:
+ end
+
+ class NullResolver < PathResolver
+- def query(path, exts, formats)
++ def query(path, exts, formats, _)
+ handler, format, variant = extract_handler_and_format_and_variant(path, formats)
+ [ActionView::Template.new("Template generated by Null Resolver", path, handler, :virtual_path => path, :format => format, :variant => variant)]
+ end
+diff --git a/actionview/test/template/render_test.rb b/actionview/test/template/render_test.rb
+index 1316f85..caf6d13 100644
+--- a/actionview/test/template/render_test.rb
++++ b/actionview/test/template/render_test.rb
+@@ -142,6 +142,13 @@ module RenderTestCases
+ assert_equal "only partial", @view.render("test/partial_only")
+ end
+
++ def test_render_outside_path
++ assert File.exist?(File.join(File.dirname(__FILE__), '../../test/abstract_unit.rb'))
++ assert_raises ActionView::MissingTemplate do
++ @view.render(:template => "../\\../test/abstract_unit.rb")
++ end
++ end
++
+ def test_render_partial
+ assert_equal "only partial", @view.render(:partial => "test/partial_only")
+ end
+--
+2.2.1
+
diff --git a/debian/patches/CVE-2016-0753.patch b/debian/patches/CVE-2016-0753.patch
new file mode 100644
index 0000000..ac0c141
--- /dev/null
+++ b/debian/patches/CVE-2016-0753.patch
@@ -0,0 +1,83 @@
+From 7a01874b75fdd62ab3626490cdf1c65c0ba659d0 Mon Sep 17 00:00:00 2001
+From: Aaron Patterson <aaron.patterson at gmail.com>
+Date: Mon, 18 Jan 2016 13:51:02 -0800
+Subject: [PATCH] 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.
+
+Conflicts:
+ activerecord/lib/active_record/scoping/default.rb
+ activesupport/lib/active_support/callbacks.rb
+
+CVE-2016-0753
+---
+ activemodel/lib/active_model/serializers/json.rb | 2 +-
+ activemodel/lib/active_model/validations.rb | 3 ++-
+ activerecord/lib/active_record/enum.rb | 2 +-
+ activerecord/lib/active_record/reflection.rb | 4 ++--
+ activesupport/lib/active_support/callbacks.rb | 2 +-
+ 5 files changed, 7 insertions(+), 6 deletions(-)
+
+--- a/activemodel/lib/active_model/serializers/json.rb
++++ b/activemodel/lib/active_model/serializers/json.rb
+@@ -10,7 +10,7 @@ module ActiveModel
+ included do
+ extend ActiveModel::Naming
+
+- class_attribute :include_root_in_json
++ class_attribute :include_root_in_json, instance_writer: false
+ self.include_root_in_json = false
+ end
+
+--- a/activemodel/lib/active_model/validations.rb
++++ b/activemodel/lib/active_model/validations.rb
+@@ -46,9 +46,10 @@ module ActiveModel
+ include HelperMethods
+
+ attr_accessor :validation_context
++ private :validation_context=
+ define_callbacks :validate, scope: :name
+
+- class_attribute :_validators
++ class_attribute :_validators, instance_writer: false
+ self._validators = Hash.new { |h,k| h[k] = [] }
+ end
+
+--- a/activerecord/lib/active_record/enum.rb
++++ b/activerecord/lib/active_record/enum.rb
+@@ -68,7 +68,7 @@ module ActiveRecord
+ # Where conditions on an enum attribute must use the ordinal value of an enum.
+ module Enum
+ def self.extended(base) # :nodoc:
+- base.class_attribute(:defined_enums)
++ base.class_attribute(:defined_enums, instance_writer: false)
+ base.defined_enums = {}
+ end
+
+--- a/activerecord/lib/active_record/reflection.rb
++++ b/activerecord/lib/active_record/reflection.rb
+@@ -4,8 +4,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
+--- a/activesupport/lib/active_support/callbacks.rb
++++ b/activesupport/lib/active_support/callbacks.rb
+@@ -726,7 +726,7 @@ module ActiveSupport
+ end
+
+ names.each do |name|
+- class_attribute "_#{name}_callbacks"
++ class_attribute "_#{name}_callbacks", instance_writer: false
+ set_callbacks name, CallbackChain.new(name, options)
+ end
+ end
diff --git a/debian/patches/series b/debian/patches/series
index d2bcd8a..59c5cd6 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1 +1,9 @@
be-carefull-with-that-bundler.patch
+CVE-2015-3226.patch
+CVE-2015-3227.patch
+CVE-2015-7576.patch
+CVE-2015-7577.patch
+CVE-2015-7581.patch
+CVE-2016-0751.patch
+CVE-2016-0752.patch
+CVE-2016-0753.patch
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/rails.git
More information about the Pkg-ruby-extras-commits
mailing list