Skip to content

Commit 5658335

Browse files
committed
Merge branch 'h1-2509647-noscript' into flavorjones-2024-security-fixes
* h1-2509647-noscript: fix: disallow 'noscript' from safe lists
2 parents 65fb72f + 1625173 commit 5658335

File tree

3 files changed

+56
-0
lines changed

3 files changed

+56
-0
lines changed

lib/rails/html/scrubbers.rb

+5
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ def validate!(var, name)
151151
end
152152
end
153153

154+
if var && name == :tags && var.include?("noscript")
155+
warn("WARNING: 'noscript' tags cannot be allowed by the PermitScrubber and will be scrubbed")
156+
var.delete("noscript")
157+
end
158+
154159
var
155160
end
156161

test/sanitizer_test.rb

+35
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,24 @@ def test_should_prune_malignmark
11361136
assert_includes(acceptable_results, actual)
11371137
end
11381138

1139+
def test_should_prune_noscript
1140+
# https://hackerone.com/reports/2509647
1141+
input, tags = "<div><noscript><p id='</noscript><script>alert(1)</script>'></noscript>", ["p", "div", "noscript"]
1142+
actual = nil
1143+
assert_output(nil, /WARNING: 'noscript' tags cannot be allowed by the PermitScrubber/) do
1144+
actual = safe_list_sanitize(input, tags: tags, attributes: %w(id))
1145+
end
1146+
1147+
acceptable_results = [
1148+
# libxml2
1149+
"<div><p id=\"&lt;/noscript&gt;&lt;script&gt;alert(1)&lt;/script&gt;\"></p></div>",
1150+
# libgumbo
1151+
"<div><p id=\"</noscript><script>alert(1)</script>\"></p></div>",
1152+
]
1153+
1154+
assert_includes(acceptable_results, actual)
1155+
end
1156+
11391157
protected
11401158
def safe_list_sanitize(input, options = {})
11411159
module_under_test::SafeListSanitizer.new.sanitize(input, options)
@@ -1247,5 +1265,22 @@ def test_should_not_be_vulnerable_to_malignmark_namespace_confusion
12471265

12481266
assert_nil(xss)
12491267
end
1268+
1269+
def test_should_not_be_vulnerable_to_noscript_attacks
1270+
# https://hackerone.com/reports/2509647
1271+
skip("browser assertion requires parse_noscript_content_as_text") unless Nokogiri::VERSION >= "1.17"
1272+
1273+
input = '<noscript><p id="</noscript><script>alert(1)</script>"></noscript>'
1274+
1275+
result = nil
1276+
assert_output(nil, /WARNING/) do
1277+
result = Rails::HTML5::SafeListSanitizer.new.sanitize(input, tags: %w(p div noscript), attributes: %w(id class style))
1278+
end
1279+
1280+
browser = Nokogiri::HTML5::Document.parse(result, parse_noscript_content_as_text: true)
1281+
xss = browser.at_xpath("//script")
1282+
1283+
assert_nil(xss)
1284+
end
12501285
end if loofah_html5_support?
12511286
end

test/scrubbers_test.rb

+16
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,22 @@ def test_does_not_allow_safelisted_mglyph
129129
assert_equal(["div", "span"], @scrubber.tags)
130130
end
131131

132+
def test_does_not_allow_safelisted_malignmark
133+
# https://hackerone.com/reports/2519936
134+
assert_output(nil, /WARNING: 'malignmark' tags cannot be allowed by the PermitScrubber/) do
135+
@scrubber.tags = ["div", "malignmark", "span"]
136+
end
137+
assert_equal(["div", "span"], @scrubber.tags)
138+
end
139+
140+
def test_does_not_allow_safelisted_noscript
141+
# https://hackerone.com/reports/2509647
142+
assert_output(nil, /WARNING: 'noscript' tags cannot be allowed by the PermitScrubber/) do
143+
@scrubber.tags = ["div", "noscript", "span"]
144+
end
145+
assert_equal(["div", "span"], @scrubber.tags)
146+
end
147+
132148
def test_leaves_text
133149
assert_scrubbed("some text")
134150
end

0 commit comments

Comments
 (0)