rails-html-sanitizer 1.4.2 → 1.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rails-html-sanitizer might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/lib/rails/html/sanitizer/version.rb +1 -1
- data/lib/rails/html/sanitizer.rb +18 -1
- data/test/sanitizer_test.rb +106 -16
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f00d9f256478eb753c8d211c3b25efa4204bbdbc9c5abf0415413c811a2e404
|
4
|
+
data.tar.gz: 65d3871aa798dfbbfb1138b666d475b590e347cdb66614d6d39b72ad3531c742
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e6e31eaa72b1a2e8356aae50600ac784f85a80828cbc49ce8061384ecd3f21a1d8eaee69845dc08537c5102728c3cc41a72cb3ed8b9789c4921038398afa61e2
|
7
|
+
data.tar.gz: 6b14a49842eaf4c3e0fbae5acd28fdf32a5deb6cd42f769aada848226847180c4d3a67a9dcbc439e1a4855699b0ea694cb4c7b6ee173391ac841bd334ae44b6f
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
## 1.4.3 / 2022-06-09
|
2
|
+
|
3
|
+
* Address a possible XSS vulnerability with certain configurations of Rails::Html::Sanitizer.
|
4
|
+
|
5
|
+
Prevent the combination of `select` and `style` as allowed tags in SafeListSanitizer.
|
6
|
+
|
7
|
+
Fixes CVE-2022-32209
|
8
|
+
|
9
|
+
*Mike Dalessio*
|
10
|
+
|
11
|
+
|
1
12
|
## 1.4.2 / 2021-08-23
|
2
13
|
|
3
14
|
* Slightly improve performance.
|
data/lib/rails/html/sanitizer.rb
CHANGED
@@ -141,8 +141,25 @@ module Rails
|
|
141
141
|
|
142
142
|
private
|
143
143
|
|
144
|
+
def loofah_using_html5?
|
145
|
+
# future-proofing, see https://github.com/flavorjones/loofah/pull/239
|
146
|
+
Loofah.respond_to?(:html5_mode?) && Loofah.html5_mode?
|
147
|
+
end
|
148
|
+
|
149
|
+
def remove_safelist_tag_combinations(tags)
|
150
|
+
if !loofah_using_html5? && tags.include?("select") && tags.include?("style")
|
151
|
+
warn("WARNING: #{self.class}: removing 'style' from safelist, should not be combined with 'select'")
|
152
|
+
tags.delete("style")
|
153
|
+
end
|
154
|
+
tags
|
155
|
+
end
|
156
|
+
|
144
157
|
def allowed_tags(options)
|
145
|
-
options[:tags]
|
158
|
+
if options[:tags]
|
159
|
+
remove_safelist_tag_combinations(options[:tags])
|
160
|
+
else
|
161
|
+
self.class.allowed_tags
|
162
|
+
end
|
146
163
|
end
|
147
164
|
|
148
165
|
def allowed_attributes(options)
|
data/test/sanitizer_test.rb
CHANGED
@@ -2,6 +2,8 @@ require "minitest/autorun"
|
|
2
2
|
require "rails-html-sanitizer"
|
3
3
|
require "rails/dom/testing/assertions/dom_assertions"
|
4
4
|
|
5
|
+
puts Nokogiri::VERSION_INFO
|
6
|
+
|
5
7
|
class SanitizersTest < Minitest::Test
|
6
8
|
include Rails::Dom::Testing::Assertions::DomAssertions
|
7
9
|
|
@@ -12,13 +14,11 @@ class SanitizersTest < Minitest::Test
|
|
12
14
|
end
|
13
15
|
|
14
16
|
def test_sanitize_nested_script
|
15
|
-
|
16
|
-
assert_equal '<script>alert("XSS");</script>', sanitizer.sanitize('<script><script></script>alert("XSS");<script><</script>/</script><script>script></script>', tags: %w(em))
|
17
|
+
assert_equal '<script>alert("XSS");</script>', safe_list_sanitize('<script><script></script>alert("XSS");<script><</script>/</script><script>script></script>', tags: %w(em))
|
17
18
|
end
|
18
19
|
|
19
20
|
def test_sanitize_nested_script_in_style
|
20
|
-
|
21
|
-
assert_equal '<script>alert("XSS");</script>', sanitizer.sanitize('<style><script></style>alert("XSS");<style><</style>/</style><style>script></style>', tags: %w(em))
|
21
|
+
assert_equal '<script>alert("XSS");</script>', safe_list_sanitize('<style><script></style>alert("XSS");<style><</style>/</style><style>script></style>', tags: %w(em))
|
22
22
|
end
|
23
23
|
|
24
24
|
class XpathRemovalTestSanitizer < Rails::Html::Sanitizer
|
@@ -54,7 +54,8 @@ class SanitizersTest < Minitest::Test
|
|
54
54
|
|
55
55
|
def test_strip_tags_with_quote
|
56
56
|
input = '<" <img src="trollface.gif" onload="alert(1)"> hi'
|
57
|
-
|
57
|
+
expected = libxml_2_9_14_recovery? ? %{<" hi} : %{ hi}
|
58
|
+
assert_equal(expected, full_sanitize(input))
|
58
59
|
end
|
59
60
|
|
60
61
|
def test_strip_invalid_html
|
@@ -75,15 +76,21 @@ class SanitizersTest < Minitest::Test
|
|
75
76
|
end
|
76
77
|
|
77
78
|
def test_remove_unclosed_tags
|
78
|
-
|
79
|
+
input = "This is <-- not\n a comment here."
|
80
|
+
expected = libxml_2_9_14_recovery? ? %{This is <-- not\n a comment here.} : %{This is }
|
81
|
+
assert_equal(expected, full_sanitize(input))
|
79
82
|
end
|
80
83
|
|
81
84
|
def test_strip_cdata
|
82
|
-
|
85
|
+
input = "This has a <![CDATA[<section>]]> here."
|
86
|
+
expected = libxml_2_9_14_recovery? ? %{This has a <![CDATA[]]> here.} : %{This has a ]]> here.}
|
87
|
+
assert_equal(expected, full_sanitize(input))
|
83
88
|
end
|
84
89
|
|
85
90
|
def test_strip_unclosed_cdata
|
86
|
-
|
91
|
+
input = "This has an unclosed <![CDATA[<section>]] here..."
|
92
|
+
expected = libxml_2_9_14_recovery? ? %{This has an unclosed <![CDATA[]] here...} : %{This has an unclosed ]] here...}
|
93
|
+
assert_equal(expected, full_sanitize(input))
|
87
94
|
end
|
88
95
|
|
89
96
|
def test_strip_blank_string
|
@@ -414,8 +421,25 @@ class SanitizersTest < Minitest::Test
|
|
414
421
|
end
|
415
422
|
|
416
423
|
def test_should_sanitize_div_background_image_unicode_encoded
|
417
|
-
|
418
|
-
|
424
|
+
[
|
425
|
+
convert_to_css_hex("url(javascript:alert(1))", false),
|
426
|
+
convert_to_css_hex("url(javascript:alert(1))", true),
|
427
|
+
convert_to_css_hex("url(https://example.com)", false),
|
428
|
+
convert_to_css_hex("url(https://example.com)", true),
|
429
|
+
].each do |propval|
|
430
|
+
raw = "background-image:" + propval
|
431
|
+
assert_empty(sanitize_css(raw))
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
def test_should_allow_div_background_image_unicode_encoded_safe_functions
|
436
|
+
[
|
437
|
+
convert_to_css_hex("rgb(255,0,0)", false),
|
438
|
+
convert_to_css_hex("rgb(255,0,0)", true),
|
439
|
+
].each do |propval|
|
440
|
+
raw = "background-image:" + propval
|
441
|
+
assert_includes(sanitize_css(raw), "background-image")
|
442
|
+
end
|
419
443
|
end
|
420
444
|
|
421
445
|
def test_should_sanitize_div_style_expression
|
@@ -433,11 +457,15 @@ class SanitizersTest < Minitest::Test
|
|
433
457
|
end
|
434
458
|
|
435
459
|
def test_should_sanitize_cdata_section
|
436
|
-
|
460
|
+
input = "<![CDATA[<span>section</span>]]>"
|
461
|
+
expected = libxml_2_9_14_recovery? ? %{<![CDATA[<span>section</span>]]>} : %{section]]>}
|
462
|
+
assert_sanitized(input, expected)
|
437
463
|
end
|
438
464
|
|
439
465
|
def test_should_sanitize_unterminated_cdata_section
|
440
|
-
|
466
|
+
input = "<![CDATA[<span>neverending..."
|
467
|
+
expected = libxml_2_9_14_recovery? ? %{<![CDATA[<span>neverending...</span>} : %{neverending...}
|
468
|
+
assert_sanitized(input, expected)
|
441
469
|
end
|
442
470
|
|
443
471
|
def test_should_not_mangle_urls_with_ampersand
|
@@ -488,7 +516,13 @@ class SanitizersTest < Minitest::Test
|
|
488
516
|
|
489
517
|
text = safe_list_sanitize(html)
|
490
518
|
|
491
|
-
|
519
|
+
acceptable_results = [
|
520
|
+
# nokogiri w/vendored+patched libxml2
|
521
|
+
%{<a href="examp<!--%22%20unsafeattr=foo()>-->le.com">test</a>},
|
522
|
+
# nokogiri w/ system libxml2
|
523
|
+
%{<a href="examp<!--%22%20unsafeattr=foo()>-->le.com">test</a>},
|
524
|
+
]
|
525
|
+
assert_includes(acceptable_results, text)
|
492
526
|
end
|
493
527
|
|
494
528
|
def test_uri_escaping_of_src_attr_in_a_tag_in_safe_list_sanitizer
|
@@ -498,7 +532,13 @@ class SanitizersTest < Minitest::Test
|
|
498
532
|
|
499
533
|
text = safe_list_sanitize(html)
|
500
534
|
|
501
|
-
|
535
|
+
acceptable_results = [
|
536
|
+
# nokogiri w/vendored+patched libxml2
|
537
|
+
%{<a src="examp<!--%22%20unsafeattr=foo()>-->le.com">test</a>},
|
538
|
+
# nokogiri w/system libxml2
|
539
|
+
%{<a src="examp<!--%22%20unsafeattr=foo()>-->le.com">test</a>},
|
540
|
+
]
|
541
|
+
assert_includes(acceptable_results, text)
|
502
542
|
end
|
503
543
|
|
504
544
|
def test_uri_escaping_of_name_attr_in_a_tag_in_safe_list_sanitizer
|
@@ -508,7 +548,13 @@ class SanitizersTest < Minitest::Test
|
|
508
548
|
|
509
549
|
text = safe_list_sanitize(html)
|
510
550
|
|
511
|
-
|
551
|
+
acceptable_results = [
|
552
|
+
# nokogiri w/vendored+patched libxml2
|
553
|
+
%{<a name="examp<!--%22%20unsafeattr=foo()>-->le.com">test</a>},
|
554
|
+
# nokogiri w/system libxml2
|
555
|
+
%{<a name="examp<!--%22%20unsafeattr=foo()>-->le.com">test</a>},
|
556
|
+
]
|
557
|
+
assert_includes(acceptable_results, text)
|
512
558
|
end
|
513
559
|
|
514
560
|
def test_uri_escaping_of_name_action_in_a_tag_in_safe_list_sanitizer
|
@@ -518,7 +564,13 @@ class SanitizersTest < Minitest::Test
|
|
518
564
|
|
519
565
|
text = safe_list_sanitize(html, attributes: ['action'])
|
520
566
|
|
521
|
-
|
567
|
+
acceptable_results = [
|
568
|
+
# nokogiri w/vendored+patched libxml2
|
569
|
+
%{<a action="examp<!--%22%20unsafeattr=foo()>-->le.com">test</a>},
|
570
|
+
# nokogiri w/system libxml2
|
571
|
+
%{<a action="examp<!--%22%20unsafeattr=foo()>-->le.com">test</a>},
|
572
|
+
]
|
573
|
+
assert_includes(acceptable_results, text)
|
522
574
|
end
|
523
575
|
|
524
576
|
def test_exclude_node_type_processing_instructions
|
@@ -529,6 +581,25 @@ class SanitizersTest < Minitest::Test
|
|
529
581
|
assert_equal("<div>text</div><b>text</b>", safe_list_sanitize("<div>text</div><!-- comment --><b>text</b>"))
|
530
582
|
end
|
531
583
|
|
584
|
+
def test_disallow_the_dangerous_safelist_combination_of_select_and_style
|
585
|
+
input = "<select><style><script>alert(1)</script></style></select>"
|
586
|
+
tags = ["select", "style"]
|
587
|
+
warning = /WARNING: Rails::Html::SafeListSanitizer: removing 'style' from safelist/
|
588
|
+
sanitized = nil
|
589
|
+
invocation = Proc.new { sanitized = safe_list_sanitize(input, tags: tags) }
|
590
|
+
|
591
|
+
if html5_mode?
|
592
|
+
# if Loofah is using an HTML5 parser,
|
593
|
+
# then "style" should be removed by the parser as an invalid child of "select"
|
594
|
+
assert_silent(&invocation)
|
595
|
+
else
|
596
|
+
# if Loofah is using an HTML4 parser,
|
597
|
+
# then SafeListSanitizer should remove "style" from the safelist
|
598
|
+
assert_output(nil, warning, &invocation)
|
599
|
+
end
|
600
|
+
refute_includes(sanitized, "style")
|
601
|
+
end
|
602
|
+
|
532
603
|
protected
|
533
604
|
|
534
605
|
def xpath_sanitize(input, options = {})
|
@@ -574,4 +645,23 @@ protected
|
|
574
645
|
ensure
|
575
646
|
Rails::Html::SafeListSanitizer.allowed_attributes = old_attributes
|
576
647
|
end
|
648
|
+
|
649
|
+
# note that this is used for testing CSS hex encoding: \\[0-9a-f]{1,6}
|
650
|
+
def convert_to_css_hex(string, escape_parens=false)
|
651
|
+
string.chars.map do |c|
|
652
|
+
if !escape_parens && (c == "(" || c == ")")
|
653
|
+
c
|
654
|
+
else
|
655
|
+
format('\00%02X', c.ord)
|
656
|
+
end
|
657
|
+
end.join
|
658
|
+
end
|
659
|
+
|
660
|
+
def libxml_2_9_14_recovery?
|
661
|
+
Nokogiri.method(:uses_libxml?).arity == -1 && Nokogiri.uses_libxml?(">= 2.9.14")
|
662
|
+
end
|
663
|
+
|
664
|
+
def html5_mode?
|
665
|
+
::Loofah.respond_to?(:html5_mode?) && ::Loofah.html5_mode?
|
666
|
+
end
|
577
667
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-html-sanitizer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rafael Mendonça França
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2022-06-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: loofah
|
@@ -103,9 +103,9 @@ licenses:
|
|
103
103
|
- MIT
|
104
104
|
metadata:
|
105
105
|
bug_tracker_uri: https://github.com/rails/rails-html-sanitizer/issues
|
106
|
-
changelog_uri: https://github.com/rails/rails-html-sanitizer/blob/v1.4.
|
107
|
-
documentation_uri: https://www.rubydoc.info/gems/rails-html-sanitizer/1.4.
|
108
|
-
source_code_uri: https://github.com/rails/rails-html-sanitizer/tree/v1.4.
|
106
|
+
changelog_uri: https://github.com/rails/rails-html-sanitizer/blob/v1.4.3/CHANGELOG.md
|
107
|
+
documentation_uri: https://www.rubydoc.info/gems/rails-html-sanitizer/1.4.3
|
108
|
+
source_code_uri: https://github.com/rails/rails-html-sanitizer/tree/v1.4.3
|
109
109
|
post_install_message:
|
110
110
|
rdoc_options: []
|
111
111
|
require_paths:
|
@@ -121,7 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
121
121
|
- !ruby/object:Gem::Version
|
122
122
|
version: '0'
|
123
123
|
requirements: []
|
124
|
-
rubygems_version: 3.
|
124
|
+
rubygems_version: 3.3.5
|
125
125
|
signing_key:
|
126
126
|
specification_version: 4
|
127
127
|
summary: This gem is responsible to sanitize HTML fragments in Rails applications.
|