From e663f084460ea56c55c3dc76f78c7caeddeeb02e Mon Sep 17 00:00:00 2001 From: Jonathan Hefner Date: Wed, 9 Sep 2020 13:41:31 -0500 Subject: [PATCH] Merge pull request from GHSA-cfjv-5498-mph5 Prior to this commit, when a translation key indicated that the translation text was HTML, the value returned by `I18n.translate` would always be marked as `html_safe`. However, the value returned by `I18n.translate` could be an untrusted value directly from `options[:default]`. This commit ensures values directly from `options[:default]` are not marked as `html_safe`. --- actionview/lib/action_view/helpers/translation_helper.rb | 9 ++++++++- actionview/test/template/translation_helper_test.rb | 7 +++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/actionview/lib/action_view/helpers/translation_helper.rb b/actionview/lib/action_view/helpers/translation_helper.rb index c9e328933e..89f984bc7f 100644 --- a/actionview/lib/action_view/helpers/translation_helper.rb +++ b/actionview/lib/action_view/helpers/translation_helper.rb @@ -96,9 +96,13 @@ module ActionView end end + html_safe_options[:default] = MISSING_TRANSLATION unless html_safe_options[:default].blank? + translation = I18n.translate(fully_resolved_key, **html_safe_options.merge(raise: i18n_raise)) - if translation.respond_to?(:map) + if translation.equal?(MISSING_TRANSLATION) + translated_text = options[:default].first + elsif translation.respond_to?(:map) translated_text = translation.map { |element| element.respond_to?(:html_safe) ? element.html_safe : element } else translated_text = translation.respond_to?(:html_safe) ? translation.html_safe : translation @@ -150,6 +154,9 @@ module ActionView alias :l :localize private + MISSING_TRANSLATION = Object.new + private_constant :MISSING_TRANSLATION + def scope_key_by_partial(key) stringified_key = key.to_s if stringified_key.start_with?(".") diff --git a/actionview/test/template/translation_helper_test.rb b/actionview/test/template/translation_helper_test.rb index 7d3ecb8441..9b0b2e3faa 100644 --- a/actionview/test/template/translation_helper_test.rb +++ b/actionview/test/template/translation_helper_test.rb @@ -247,6 +247,13 @@ class TranslationHelperTest < ActiveSupport::TestCase assert_equal false, translation.html_safe? end + def test_translate_does_not_mark_unsourced_string_default_as_html_safe + untrusted_string = "" + translation = translate(:"translations.missing", default: [:"translations.missing_html", untrusted_string]) + assert_equal untrusted_string, translation + assert_not_predicate translation, :html_safe? + end + def test_translate_with_string_default translation = translate(:'translations.missing', default: "A Generic String") assert_equal "A Generic String", translation