Possible XSS vulnerability with certain configurations of rails-html-sanitizer 1.6.0
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.
| Package | Affected versions | Patched versions |
|---|---|---|
rails-html-sanitizerRubyGems | >= 1.6.0, < 1.6.1 | 1.6.1 |
Affected products
4- Range: >= 1.6.0, < 1.6.1
- ghsa-coords2 versionspkg:gem/rails-html-sanitizerpkg:rpm/opensuse/rubygem-rails-html-sanitizer&distro=openSUSE%20Tumbleweed
>= 1.6.0, < 1.6.1+ 1 more
- (no CPE)range: >= 1.6.0, < 1.6.1
- (no CPE)range: < 1.7.0-1.1
- rails/rails-html-sanitizerv5Range: >= 1.6.0, < 1.6.1
Patches
1f02ffbb8465efix: Namespace confusion when disallowing 'svg' or 'math'
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><script>alert(1)</script></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><style class='</style>alert(1)'>", + # 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><style class='</style>alert(1)'>", + # 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><img src=: onerror=alert(1)></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- github.com/advisories/GHSA-2x5m-9ch4-qgrrghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-53987ghsaADVISORY
- github.com/rails/rails-html-sanitizer/commit/f02ffbb8465e73920b6de0da940f5530f855965eghsax_refsource_MISCWEB
- github.com/rails/rails-html-sanitizer/security/advisories/GHSA-2x5m-9ch4-qgrrghsax_refsource_CONFIRMWEB
- github.com/rubysec/ruby-advisory-db/blob/master/gems/rails-html-sanitizer/CVE-2024-53987.ymlghsaWEB
News mentions
0No linked articles in our index yet.