Skip to content

Commit 0713caf

Browse files
committed
fix: escape CDATA nodes using Loofah's escaping methods
Also, notably, document the decisions behind this approach in a decision record.
1 parent e6d52d3 commit 0713caf

File tree

2 files changed

+63
-3
lines changed

2 files changed

+63
-3
lines changed

lib/rails/html/scrubbers.rb

+3-3
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ def attributes=(attributes)
6161
end
6262

6363
def scrub(node)
64-
if node.cdata?
65-
text = node.document.create_text_node node.text
66-
node.replace text
64+
if Loofah::HTML5::Scrub.cdata_needs_escaping?(node)
65+
replacement = Loofah::HTML5::Scrub.cdata_escape(node)
66+
node.replace(replacement)
6767
return CONTINUE
6868
end
6969
return CONTINUE if skip_node?(node)

test/sanitizer_test.rb

+60
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,66 @@ def test_scrubbing_svg_attr_values_that_allow_ref
641641
assert_equal(expected, actual)
642642
end
643643

644+
def test_style_with_css_payload
645+
input, tags = "<style>div > span { background: \"red\"; }</style>", ["style"]
646+
expected = "<style>div &gt; span { background: \"red\"; }</style>"
647+
actual = safe_list_sanitize(input, tags: tags)
648+
649+
assert_equal(expected, actual)
650+
end
651+
652+
def test_combination_of_select_and_style_with_css_payload
653+
input, tags = "<select><style>div > span { background: \"red\"; }</style></select>", ["select", "style"]
654+
expected = "<select><style>div &gt; span { background: \"red\"; }</style></select>"
655+
actual = safe_list_sanitize(input, tags: tags)
656+
657+
assert_equal(expected, actual)
658+
end
659+
660+
def test_combination_of_select_and_style_with_script_payload
661+
input, tags = "<select><style><script>alert(1)</script></style></select>", ["select", "style"]
662+
expected = "<select><style>&lt;script&gt;alert(1)&lt;/script&gt;</style></select>"
663+
actual = safe_list_sanitize(input, tags: tags)
664+
665+
assert_equal(expected, actual)
666+
end
667+
668+
def test_combination_of_svg_and_style_with_script_payload
669+
input, tags = "<svg><style><script>alert(1)</script></style></svg>", ["svg", "style"]
670+
expected = "<svg><style>&lt;script&gt;alert(1)&lt;/script&gt;</style></svg>"
671+
actual = safe_list_sanitize(input, tags: tags)
672+
673+
assert_equal(expected, actual)
674+
end
675+
676+
def test_combination_of_math_and_style_with_img_payload
677+
input, tags = "<math><style><img src=x onerror=alert(1)></style></math>", ["math", "style"]
678+
expected = "<math><style>&lt;img src=x onerror=alert(1)&gt;</style></math>"
679+
actual = safe_list_sanitize(input, tags: tags)
680+
681+
assert_equal(expected, actual)
682+
683+
input, tags = "<math><style><img src=x onerror=alert(1)></style></math>", ["math", "style", "img"]
684+
expected = "<math><style>&lt;img src=x onerror=alert(1)&gt;</style></math>"
685+
actual = safe_list_sanitize(input, tags: tags)
686+
687+
assert_equal(expected, actual)
688+
end
689+
690+
def test_combination_of_svg_and_style_with_img_payload
691+
input, tags = "<svg><style><img src=x onerror=alert(1)></style></svg>", ["svg", "style"]
692+
expected = "<svg><style>&lt;img src=x onerror=alert(1)&gt;</style></svg>"
693+
actual = safe_list_sanitize(input, tags: tags)
694+
695+
assert_equal(expected, actual)
696+
697+
input, tags = "<svg><style><img src=x onerror=alert(1)></style></svg>", ["svg", "style", "img"]
698+
expected = "<svg><style>&lt;img src=x onerror=alert(1)&gt;</style></svg>"
699+
actual = safe_list_sanitize(input, tags: tags)
700+
701+
assert_equal(expected, actual)
702+
end
703+
644704
protected
645705

646706
def xpath_sanitize(input, options = {})

0 commit comments

Comments
 (0)