VYPR
Moderate severityNVD Advisory· Published Dec 7, 2013· Updated Apr 29, 2026

CVE-2013-4492

CVE-2013-4492

Description

Cross-site scripting (XSS) vulnerability in exceptions.rb in the i18n gem before 0.6.6 for Ruby allows remote attackers to inject arbitrary web script or HTML via a crafted I18n::MissingTranslationData.new call.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
i18nRubyGems
< 0.6.60.6.6

Affected products

1

Patches

2
92b57b1e4f84

The I18n::MissingTranslation exception escapes key names for its html_message

https://github.com/ruby-i18n/i18nChristopher DellDec 3, 2013via ghsa
2 files changed · +32 6
  • lib/i18n/exceptions.rb+25 3 modified
    @@ -1,3 +1,5 @@
    +require 'cgi'
    +
     module I18n
       # Handles exceptions raised in the backend. All exceptions except for
       # MissingTranslationData exceptions are re-thrown. When a MissingTranslationData
    @@ -7,7 +9,19 @@ class ExceptionHandler
         include Module.new {
           def call(exception, locale, key, options)
             if exception.is_a?(MissingTranslation)
    -          options[:rescue_format] == :html ? exception.html_message : exception.message
    +          #
    +          # TODO: this block is to be replaced by `exception.message` when
    +          # rescue_format is removed
    +          if options[:rescue_format] == :html
    +            if @rescue_format_deprecation
    +              $stderr.puts "[DEPRECATED] I18n's :recue_format option will be removed from a future release. All exception messages will be plain text. If you need the exception handler to return an html format please set or pass a custom exception handler."
    +              @rescue_format_deprecation = true
    +            end
    +            exception.html_message
    +          else
    +            exception.message
    +          end
    +
             elsif exception.is_a?(Exception)
               raise exception
             else
    @@ -45,8 +59,9 @@ def initialize(locale, key, options = nil)
           end
     
           def html_message
    -        key = keys.last.to_s.gsub('_', ' ').gsub(/\b('?[a-z])/) { $1.capitalize }
    -        %(<span class="translation_missing" title="translation missing: #{keys.join('.')}">#{key}</span>)
    +        key  = CGI.escape_html titleize(keys.last)
    +        path = CGI.escape_html keys.join('.')
    +        %(<span class="translation_missing" title="translation missing: #{path}">#{key}</span>)
           end
     
           def keys
    @@ -63,6 +78,13 @@ def message
           def to_exception
             MissingTranslationData.new(locale, key, options)
           end
    +
    +      protected
    +
    +      # TODO : remove when #html_message is removed
    +      def titleize(key)
    +        key.to_s.gsub('_', ' ').gsub(/\b('?[a-z])/) { $1.capitalize }
    +      end
         end
     
         include Base
    
  • test/i18n/exceptions_test.rb+7 3 modified
    @@ -28,9 +28,13 @@ def test_invalid_locale_stores_locale
       end
     
       test "MissingTranslationData html_message is a span with the titlelized last key token" do
    -    force_missing_translation_data do |exception|
    -      assert_equal '<span class="translation_missing" title="translation missing: de.bar.foo">Foo</span>', exception.html_message
    -    end
    +    exception = I18n::MissingTranslationData.new(:de, :foo, :scope => :bar)
    +    assert_equal '<span class="translation_missing" title="translation missing: de.bar.foo">Foo</span>', exception.html_message
    +  end
    +
    +  test "MissingTranslationData html_message html escapes key names" do
    +    exception = I18n::MissingTranslationData.new(:de, '<script>Evil</script>', :scope => '<iframe src="example.com" />')
    +    assert_equal '<span class="translation_missing" title="translation missing: de.&lt;iframe src=&quot;example.com&quot; /&gt;.&lt;script&gt;Evil&lt;/script&gt;">&lt;Script&gt;Evil&lt;/Script&gt;</span>', exception.html_message
       end
     
       test "ExceptionHandler returns the html_message if :rescue_format => :html was given" do
    
92b57b1e4f84

The I18n::MissingTranslation exception escapes key names for its html_message

https://github.com/svenfuchs/i18nChristopher DellDec 3, 2013via ghsa
2 files changed · +32 6
  • lib/i18n/exceptions.rb+25 3 modified
    @@ -1,3 +1,5 @@
    +require 'cgi'
    +
     module I18n
       # Handles exceptions raised in the backend. All exceptions except for
       # MissingTranslationData exceptions are re-thrown. When a MissingTranslationData
    @@ -7,7 +9,19 @@ class ExceptionHandler
         include Module.new {
           def call(exception, locale, key, options)
             if exception.is_a?(MissingTranslation)
    -          options[:rescue_format] == :html ? exception.html_message : exception.message
    +          #
    +          # TODO: this block is to be replaced by `exception.message` when
    +          # rescue_format is removed
    +          if options[:rescue_format] == :html
    +            if @rescue_format_deprecation
    +              $stderr.puts "[DEPRECATED] I18n's :recue_format option will be removed from a future release. All exception messages will be plain text. If you need the exception handler to return an html format please set or pass a custom exception handler."
    +              @rescue_format_deprecation = true
    +            end
    +            exception.html_message
    +          else
    +            exception.message
    +          end
    +
             elsif exception.is_a?(Exception)
               raise exception
             else
    @@ -45,8 +59,9 @@ def initialize(locale, key, options = nil)
           end
     
           def html_message
    -        key = keys.last.to_s.gsub('_', ' ').gsub(/\b('?[a-z])/) { $1.capitalize }
    -        %(<span class="translation_missing" title="translation missing: #{keys.join('.')}">#{key}</span>)
    +        key  = CGI.escape_html titleize(keys.last)
    +        path = CGI.escape_html keys.join('.')
    +        %(<span class="translation_missing" title="translation missing: #{path}">#{key}</span>)
           end
     
           def keys
    @@ -63,6 +78,13 @@ def message
           def to_exception
             MissingTranslationData.new(locale, key, options)
           end
    +
    +      protected
    +
    +      # TODO : remove when #html_message is removed
    +      def titleize(key)
    +        key.to_s.gsub('_', ' ').gsub(/\b('?[a-z])/) { $1.capitalize }
    +      end
         end
     
         include Base
    
  • test/i18n/exceptions_test.rb+7 3 modified
    @@ -28,9 +28,13 @@ def test_invalid_locale_stores_locale
       end
     
       test "MissingTranslationData html_message is a span with the titlelized last key token" do
    -    force_missing_translation_data do |exception|
    -      assert_equal '<span class="translation_missing" title="translation missing: de.bar.foo">Foo</span>', exception.html_message
    -    end
    +    exception = I18n::MissingTranslationData.new(:de, :foo, :scope => :bar)
    +    assert_equal '<span class="translation_missing" title="translation missing: de.bar.foo">Foo</span>', exception.html_message
    +  end
    +
    +  test "MissingTranslationData html_message html escapes key names" do
    +    exception = I18n::MissingTranslationData.new(:de, '<script>Evil</script>', :scope => '<iframe src="example.com" />')
    +    assert_equal '<span class="translation_missing" title="translation missing: de.&lt;iframe src=&quot;example.com&quot; /&gt;.&lt;script&gt;Evil&lt;/script&gt;">&lt;Script&gt;Evil&lt;/Script&gt;</span>', exception.html_message
       end
     
       test "ExceptionHandler returns the html_message if :rescue_format => :html was given" do
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

19

News mentions

0

No linked articles in our index yet.