Skip to content

Commit 3fe22a8

Browse files
committed
Merge branch 'h1-2519936-foreign-ns-confusion' into flavorjones-2024-security-fixes
* h1-2519936-foreign-ns-confusion: fix: Namespace confusion when disallowing 'svg' or 'math'
2 parents d7a94c1 + f02ffbb commit 3fe22a8

File tree

2 files changed

+68
-2
lines changed

2 files changed

+68
-2
lines changed

lib/rails/html/scrubbers.rb

+5-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,11 @@ def keep_node?(node)
101101
end
102102

103103
def scrub_node(node)
104-
node.before(node.children) unless prune # strip
104+
# If a node has a namespace, then it's a tag in either a `math` or `svg` foreign context,
105+
# and we should always prune it to avoid namespace confusion and mutation XSS vectors.
106+
unless prune || node.namespace
107+
node.before(node.children)
108+
end
105109
node.remove
106110
end
107111

test/sanitizer_test.rb

+63-1
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,7 @@ def test_combination_of_svg_and_style_with_script_payload
918918
# libxml2
919919
"<svg><style>&lt;script&gt;alert(1)&lt;/script&gt;</style></svg>",
920920
# libgumbo
921-
"<svg><style>alert(1)</style></svg>"
921+
"<svg><style></style></svg>",
922922
]
923923

924924
assert_includes(acceptable_results, actual)
@@ -1004,6 +1004,48 @@ def test_combination_of_math_and_style_with_escaped_img_payload
10041004
assert_includes(acceptable_results, actual)
10051005
end
10061006

1007+
def test_combination_of_style_and_disallowed_svg_with_script_payload
1008+
# https://hackerone.com/reports/2519936
1009+
input, tags = "<svg><style><style class='</style><script>alert(1)</script>'>", ["style"]
1010+
actual = safe_list_sanitize(input, tags: tags)
1011+
acceptable_results = [
1012+
# libxml2
1013+
"<style>&lt;style class='</style>alert(1)'&gt;",
1014+
# libgumbo
1015+
"",
1016+
]
1017+
1018+
assert_includes(acceptable_results, actual)
1019+
end
1020+
1021+
def test_combination_of_style_and_disallowed_math_with_script_payload
1022+
# https://hackerone.com/reports/2519936
1023+
input, tags = "<math><style><style class='</style><script>alert(1)</script>'>", ["style"]
1024+
actual = safe_list_sanitize(input, tags: tags)
1025+
acceptable_results = [
1026+
# libxml2
1027+
"<style>&lt;style class='</style>alert(1)'&gt;",
1028+
# libgumbo
1029+
"",
1030+
]
1031+
1032+
assert_includes(acceptable_results, actual)
1033+
end
1034+
1035+
def test_math_with_disallowed_mtext_and_img_payload
1036+
# https://hackerone.com/reports/2519941
1037+
input, tags = "<math><mtext><table><mglyph><style><img src=: onerror=alert(1)>", ["math", "style"]
1038+
actual = safe_list_sanitize(input, tags: tags)
1039+
acceptable_results = [
1040+
# libxml2
1041+
"<math><style>&lt;img src=: onerror=alert(1)&gt;</style></math>",
1042+
# libgumbo
1043+
"<math></math>",
1044+
]
1045+
1046+
assert_includes(acceptable_results, actual)
1047+
end
1048+
10071049
def test_should_sanitize_illegal_style_properties
10081050
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;)
10091051
expected = %(display:block;width:100%;height:100%;background-color:black;background-x:center;background-y:center;)
@@ -1113,5 +1155,25 @@ def test_should_not_be_vulnerable_to_nokogiri_foreign_style_serialization_bug
11131155

11141156
assert_nil(xss)
11151157
end
1158+
1159+
def test_should_not_be_vulnerable_to_ns_confusion_2519936
1160+
# https://hackerone.com/reports/2519936
1161+
input = "<math><style><style class='</style><script>alert(1)</script>'>"
1162+
result = Rails::HTML5::SafeListSanitizer.new.sanitize(input, tags: ["style"])
1163+
browser = Nokogiri::HTML5::Document.parse(result)
1164+
xss = browser.at_xpath("//script")
1165+
1166+
assert_nil(xss)
1167+
end
1168+
1169+
def test_should_not_be_vulnerable_to_ns_confusion_2519941
1170+
# https://hackerone.com/reports/2519941
1171+
input = "<math><mtext><table><mglyph><style><img src=: onerror=alert(1)>"
1172+
result = Rails::HTML5::SafeListSanitizer.new.sanitize(input, tags: %w(math style))
1173+
browser = Nokogiri::HTML5::Document.parse(result)
1174+
xss = browser.at_xpath("//img/@onerror")
1175+
1176+
assert_nil(xss)
1177+
end
11161178
end if loofah_html5_support?
11171179
end

0 commit comments

Comments
 (0)