From 857f2e4a6a6c289028a03297673bc058c4a4d235 Mon Sep 17 00:00:00 2001 From: ooooooo_q Date: Fri, 5 Jan 2024 12:00:02 +0900 Subject: [PATCH] fix XSS vulnerability when using translation [CVE-2024-26143] --- .../lib/abstract_controller/translation.rb | 24 +++++++++++++- actionpack/test/abstract/translation_test.rb | 31 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/actionpack/lib/abstract_controller/translation.rb b/actionpack/lib/abstract_controller/translation.rb index 86285c60fa1..8a139d490ec 100644 --- a/actionpack/lib/abstract_controller/translation.rb +++ b/actionpack/lib/abstract_controller/translation.rb @@ -23,7 +23,25 @@ module AbstractController key = "#{path}.#{action_name}#{key}" end - ActiveSupport::HtmlSafeTranslation.translate(key, **options) + if options[:default] + options[:default] = [options[:default]] unless options[:default].is_a?(Array) + options[:default] = options[:default].map do |value| + value.is_a?(String) ? ERB::Util.html_escape(value) : value + end + end + + if options[:raise].nil? + options[:default] = [] unless options[:default] + options[:default] << MISSING_TRANSLATION + end + + result = ActiveSupport::HtmlSafeTranslation.translate(key, **options) + + if result == MISSING_TRANSLATION + +"translation missing: #{key}" + else + result + end end alias :t :translate @@ -32,5 +50,9 @@ module AbstractController I18n.localize(object, **options) end alias :l :localize + + private + MISSING_TRANSLATION = -(2**60) + private_constant :MISSING_TRANSLATION end end diff --git a/actionpack/test/abstract/translation_test.rb b/actionpack/test/abstract/translation_test.rb index c1bc8a050a3..3d5483381c1 100644 --- a/actionpack/test/abstract/translation_test.rb +++ b/actionpack/test/abstract/translation_test.rb @@ -83,6 +83,22 @@ module AbstractController end end + def test_default_translation_as_safe_html + @controller.stub :action_name, :index do + translation = @controller.t(".twoz", default: [""]) + assert_equal "<tag>", translation + assert_equal true, translation.html_safe? + end + end + + def test_default_translation_with_raise_as_safe_html + @controller.stub :action_name, :index do + translation = @controller.t(".twoz", raise: true, default: [""]) + assert_equal "<tag>", translation + assert_equal true, translation.html_safe? + end + end + def test_localize time, expected = Time.gm(2000), "Sat, 01 Jan 2000 00:00:00 +0000" I18n.stub :localize, expected do @@ -126,6 +142,21 @@ module AbstractController assert_equal true, translation.html_safe? end end + + def test_translate_marks_translation_with_missing_html_key_as_safe_html + @controller.stub :action_name, :index do + translation = @controller.t(".html") + assert_equal "translation missing: .html", translation + assert_equal false, translation.html_safe? + end + end + def test_translate_marks_translation_with_missing_nested_html_key_as_safe_html + @controller.stub :action_name, :index do + translation = @controller.t("..html") + assert_equal "translation missing: abstract_controller.testing.translation.index..html", translation + assert_equal false, translation.html_safe? + end + end end end end