VYPR
Low severityNVD Advisory· Published Dec 2, 2024· Updated Dec 3, 2024

Possible XSS vulnerability with certain configurations of rails-html-sanitizer 1.6.0

CVE-2024-53987

Description

rails-html-sanitizer is responsible for sanitizing HTML fragments in Rails applications. There is a possible XSS vulnerability with certain configurations of Rails::HTML::Sanitizer 1.6.0 when used with Rails >= 7.1.0. A possible XSS vulnerability with certain configurations of Rails::HTML::Sanitizer may allow an attacker to inject content if HTML5 sanitization is enabled and the application developer has overridden the sanitizer's allowed tags where the "style" element is explicitly allowed and the "svg" or "math" element is not allowed. This vulnerability is fixed in 1.6.1.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

rails-html-sanitizer 1.6.0 has a XSS vulnerability when HTML5 sanitization is enabled and 'style' is allowed but 'svg' or 'math' is not, fixed in 1.6.1.

Vulnerability

CVE-2024-53987 is a cross-site scripting (XSS) vulnerability in rails-html-sanitizer version 1.6.0 when used with Rails >= 7.1.0. The root cause is a namespace confusion in the HTML5 sanitizer: if an application explicitly allows the style element but disallows svg or math elements, an attacker can bypass sanitization by nesting a style element inside a disallowed svg or math element. This allows the injection of arbitrary HTML or JavaScript [2][4].

Exploitation

To exploit this vulnerability, an attacker must craft input containing a style element inside an svg or math element, such as '>. The attack requires that the application uses HTML5 sanitization (the default in Rails 7.1+) and that the developer has overridden the allowed tags to include style while excluding svg and math. This can happen via config.action_view.sanitized_allowed_tags, the :tags option in the sanitize helper, or by setting Rails::HTML5::SafeListSanitizer.allowed_tags [4].

Impact

Successful exploitation allows an attacker to inject arbitrary JavaScript into the application's output, leading to XSS attacks. This could result in session theft, defacement, or other malicious actions performed in the context of the victim's browser [4].

Mitigation

The vulnerability is fixed in rails-html-sanitizer version 1.6.1. Users should upgrade immediately. As a workaround, developers can ensure that if style is allowed, both svg and math are also allowed in the sanitizer's allowed tags. The fix addresses the namespace confusion by properly handling the interaction between these elements [3][4].

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
rails-html-sanitizerRubyGems
>= 1.6.0, < 1.6.11.6.1

Affected products

4

Patches

1
f02ffbb8465e

fix: Namespace confusion when disallowing 'svg' or 'math'

https://github.com/rails/rails-html-sanitizerMike DalessioNov 30, 2024via ghsa
2 files changed · +68 2
  • lib/rails/html/scrubbers.rb+5 1 modified
    @@ -101,7 +101,11 @@ def keep_node?(node)
             end
     
             def scrub_node(node)
    -          node.before(node.children) unless prune # strip
    +          # If a node has a namespace, then it's a tag in either a `math` or `svg` foreign context,
    +          # and we should always prune it to avoid namespace confusion and mutation XSS vectors.
    +          unless prune || node.namespace
    +            node.before(node.children)
    +          end
               node.remove
             end
     
    
  • test/sanitizer_test.rb+63 1 modified
    @@ -918,7 +918,7 @@ def test_combination_of_svg_and_style_with_script_payload
             # libxml2
             "<svg><style>&lt;script&gt;alert(1)&lt;/script&gt;</style></svg>",
             # libgumbo
    -        "<svg><style>alert(1)</style></svg>"
    +        "<svg><style></style></svg>",
           ]
     
           assert_includes(acceptable_results, actual)
    @@ -976,6 +976,48 @@ def test_combination_of_svg_and_style_with_img_payload_2
           assert_includes(acceptable_results, actual)
         end
     
    +    def test_combination_of_style_and_disallowed_svg_with_script_payload
    +      # https://hackerone.com/reports/2519936
    +      input, tags = "<svg><style><style class='</style><script>alert(1)</script>'>", ["style"]
    +      actual = safe_list_sanitize(input, tags: tags)
    +      acceptable_results = [
    +        # libxml2
    +        "<style>&lt;style class='</style>alert(1)'&gt;",
    +        # libgumbo
    +        "",
    +      ]
    +
    +      assert_includes(acceptable_results, actual)
    +    end
    +
    +    def test_combination_of_style_and_disallowed_math_with_script_payload
    +      # https://hackerone.com/reports/2519936
    +      input, tags = "<math><style><style class='</style><script>alert(1)</script>'>", ["style"]
    +      actual = safe_list_sanitize(input, tags: tags)
    +      acceptable_results = [
    +        # libxml2
    +        "<style>&lt;style class='</style>alert(1)'&gt;",
    +        # libgumbo
    +        "",
    +      ]
    +
    +      assert_includes(acceptable_results, actual)
    +    end
    +
    +    def test_math_with_disallowed_mtext_and_img_payload
    +      # https://hackerone.com/reports/2519941
    +      input, tags = "<math><mtext><table><mglyph><style><img src=: onerror=alert(1)>", ["math", "style"]
    +      actual = safe_list_sanitize(input, tags: tags)
    +      acceptable_results = [
    +        # libxml2
    +        "<math><style>&lt;img src=: onerror=alert(1)&gt;</style></math>",
    +        # libgumbo
    +        "<math></math>",
    +      ]
    +
    +      assert_includes(acceptable_results, actual)
    +    end
    +
         def test_should_sanitize_illegal_style_properties
           raw      = %(display:block; position:absolute; left:0; top:0; width:100%; height:100%; z-index:1; background-color:black; background-image:url(http://www.ragingplatypus.com/i/cam-full.jpg); background-x:center; background-y:center; background-repeat:repeat;)
           expected = %(display:block;width:100%;height:100%;background-color:black;background-x:center;background-y:center;)
    @@ -1075,5 +1117,25 @@ class HTML4SafeListSanitizerTest < Minitest::Test
       class HTML5SafeListSanitizerTest < Minitest::Test
         @module_under_test = Rails::HTML5
         include SafeListSanitizerTest
    +
    +    def test_should_not_be_vulnerable_to_ns_confusion_2519936
    +      # https://hackerone.com/reports/2519936
    +      input = "<math><style><style class='</style><script>alert(1)</script>'>"
    +      result = Rails::HTML5::SafeListSanitizer.new.sanitize(input, tags: ["style"])
    +      browser = Nokogiri::HTML5::Document.parse(result)
    +      xss = browser.at_xpath("//script")
    +
    +      assert_nil(xss)
    +    end
    +
    +    def test_should_not_be_vulnerable_to_ns_confusion_2519941
    +      # https://hackerone.com/reports/2519941
    +      input = "<math><mtext><table><mglyph><style><img src=: onerror=alert(1)>"
    +      result = Rails::HTML5::SafeListSanitizer.new.sanitize(input, tags: %w(math style))
    +      browser = Nokogiri::HTML5::Document.parse(result)
    +      xss = browser.at_xpath("//img/@onerror")
    +
    +      assert_nil(xss)
    +    end
       end if loofah_html5_support?
     end
    

Vulnerability mechanics

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

References

5

News mentions

0

No linked articles in our index yet.