Skip to content

Commit 373fc62

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 68ccf7e commit 373fc62

File tree

2 files changed

+63
-3
lines changed

2 files changed

+63
-3
lines changed

lib/rails/html/scrubbers.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ def attributes=(attributes)
6262
end
6363

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

test/sanitizer_test.rb

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,66 @@ def test_scrubbing_svg_attr_values_that_allow_ref
647647
assert_equal(expected, actual)
648648
end
649649

650+
def test_style_with_css_payload
651+
input, tags = "<style>div > span { background: \"red\"; }</style>", ["style"]
652+
expected = "<style>div &gt; span { background: \"red\"; }</style>"
653+
actual = safe_list_sanitize(input, tags: tags)
654+
655+
assert_equal(expected, actual)
656+
end
657+
658+
def test_combination_of_select_and_style_with_css_payload
659+
input, tags = "<select><style>div > span { background: \"red\"; }</style></select>", ["select", "style"]
660+
expected = "<select><style>div &gt; span { background: \"red\"; }</style></select>"
661+
actual = safe_list_sanitize(input, tags: tags)
662+
663+
assert_equal(expected, actual)
664+
end
665+
666+
def test_combination_of_select_and_style_with_script_payload
667+
input, tags = "<select><style><script>alert(1)</script></style></select>", ["select", "style"]
668+
expected = "<select><style>&lt;script&gt;alert(1)&lt;/script&gt;</style></select>"
669+
actual = safe_list_sanitize(input, tags: tags)
670+
671+
assert_equal(expected, actual)
672+
end
673+
674+
def test_combination_of_svg_and_style_with_script_payload
675+
input, tags = "<svg><style><script>alert(1)</script></style></svg>", ["svg", "style"]
676+
expected = "<svg><style>&lt;script&gt;alert(1)&lt;/script&gt;</style></svg>"
677+
actual = safe_list_sanitize(input, tags: tags)
678+
679+
assert_equal(expected, actual)
680+
end
681+
682+
def test_combination_of_math_and_style_with_img_payload
683+
input, tags = "<math><style><img src=x onerror=alert(1)></style></math>", ["math", "style"]
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+
689+
input, tags = "<math><style><img src=x onerror=alert(1)></style></math>", ["math", "style", "img"]
690+
expected = "<math><style>&lt;img src=x onerror=alert(1)&gt;</style></math>"
691+
actual = safe_list_sanitize(input, tags: tags)
692+
693+
assert_equal(expected, actual)
694+
end
695+
696+
def test_combination_of_svg_and_style_with_img_payload
697+
input, tags = "<svg><style><img src=x onerror=alert(1)></style></svg>", ["svg", "style"]
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+
703+
input, tags = "<svg><style><img src=x onerror=alert(1)></style></svg>", ["svg", "style", "img"]
704+
expected = "<svg><style>&lt;img src=x onerror=alert(1)&gt;</style></svg>"
705+
actual = safe_list_sanitize(input, tags: tags)
706+
707+
assert_equal(expected, actual)
708+
end
709+
650710
protected
651711

652712
def xpath_sanitize(input, options = {})

0 commit comments

Comments
 (0)