From 58ed245e80a8710fbe31e91417bfd19f9f934cc4 Mon Sep 17 00:00:00 2001
From: John Hawthorn <john@hawthorn.email>
Date: Mon, 4 Mar 2019 18:24:51 -0800
Subject: [PATCH] Only accept formats from registered mime types

[CVE-2019-5418]
[CVE-2019-5419]
---
 .../lib/action_dispatch/http/mime_negotiation.rb |  6 +++++-
 .../test/controller/mime/respond_to_test.rb      | 14 ++++++++------
 .../new_base/content_negotiation_test.rb         | 16 +++++++++++++---
 3 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
index 53a98c5d0a..00fd3d03df 100644
--- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb
+++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
@@ -61,7 +61,7 @@ module ActionDispatch
                               false
                             end
 
-          if params_readable
+          v = if params_readable
             Array(Mime[parameters[:format]])
           elsif use_accept_header && valid_accept_header
             accepts
@@ -70,6 +70,10 @@ module ActionDispatch
           else
             [Mime::HTML]
           end
+
+          v.select do |format|
+            format.symbol || format.ref == "*/*"
+          end
         end
       end
 
diff --git a/actionpack/test/controller/mime/respond_to_test.rb b/actionpack/test/controller/mime/respond_to_test.rb
index 66d2fd7716..07ad0085fc 100644
--- a/actionpack/test/controller/mime/respond_to_test.rb
+++ b/actionpack/test/controller/mime/respond_to_test.rb
@@ -87,9 +87,9 @@ class RespondToController < ActionController::Base
 
   def custom_type_handling
     respond_to do |type|
-      type.html { render :text => "HTML"    }
-      type.custom("application/crazy-xml")  { render :text => "Crazy XML"  }
-      type.all  { render :text => "Nothing" }
+      type.html { render text: "HTML"    }
+      type.custom("application/fancy-xml")  { render text: "Fancy XML"  }
+      type.all  { render text: "Nothing" }
     end
   end
 
@@ -269,12 +269,14 @@ class RespondToControllerTest < ActionController::TestCase
     @request.host = "www.example.com"
     Mime::Type.register_alias("text/html", :iphone)
     Mime::Type.register("text/x-mobile", :mobile)
+    Mime::Type.register("application/fancy-xml", :fancy_xml)
   end
 
   def teardown
     super
     Mime::Type.unregister(:iphone)
     Mime::Type.unregister(:mobile)
+    Mime::Type.unregister(:fancy_xml)
   end
 
   def test_html
@@ -430,10 +432,10 @@ class RespondToControllerTest < ActionController::TestCase
   end
 
   def test_custom_types
-    @request.accept = "application/crazy-xml"
+    @request.accept = "application/fancy-xml"
     get :custom_type_handling
-    assert_equal "application/crazy-xml", @response.content_type
-    assert_equal 'Crazy XML', @response.body
+    assert_equal "application/fancy-xml", @response.content_type
+    assert_equal "Fancy XML", @response.body
 
     @request.accept = "text/html"
     get :custom_type_handling
diff --git a/actionpack/test/controller/new_base/content_negotiation_test.rb b/actionpack/test/controller/new_base/content_negotiation_test.rb
index 5fd5946619..57bf16ac9c 100644
--- a/actionpack/test/controller/new_base/content_negotiation_test.rb
+++ b/actionpack/test/controller/new_base/content_negotiation_test.rb
@@ -19,9 +19,19 @@ module ContentNegotiation
       assert_body "Hello world */*!"
     end
 
-    test "Not all mimes are converted to symbol" do
-      get "/content_negotiation/basic/all", {}, "HTTP_ACCEPT" => "text/plain, mime/another"
-      assert_body '[:text, "mime/another"]'
+    test "A js or */* Accept header will return HTML" do
+      get "/content_negotiation/basic/hello", {}, { "HTTP_ACCEPT" => "text/javascript, */*" }
+      assert_body "Hello world text/html!"
+    end
+
+    test "A js or */* Accept header on xhr will return HTML" do
+      xhr :get, "/content_negotiation/basic/hello", {}, { "HTTP_ACCEPT" => "text/javascript, */*" }
+      assert_body "Hello world text/javascript!"
+    end
+
+    test "Unregistered mimes are ignored" do
+      get "/content_negotiation/basic/all", {}, { "HTTP_ACCEPT" => "text/plain, mime/another" }
+      assert_body '[:text]'
     end
   end
 end
-- 
2.21.0

