rails-html-sanitizer 1.4.3 → 1.4.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2f00d9f256478eb753c8d211c3b25efa4204bbdbc9c5abf0415413c811a2e404
4
- data.tar.gz: 65d3871aa798dfbbfb1138b666d475b590e347cdb66614d6d39b72ad3531c742
3
+ metadata.gz: a74021096590326ee357971bec71d2c4507a95cdaf05c8e21d383ce18fee18d3
4
+ data.tar.gz: faad0d5f268dad601b633b03912e353fcc2d760fceb253d9cde2064b010b997a
5
5
  SHA512:
6
- metadata.gz: e6e31eaa72b1a2e8356aae50600ac784f85a80828cbc49ce8061384ecd3f21a1d8eaee69845dc08537c5102728c3cc41a72cb3ed8b9789c4921038398afa61e2
7
- data.tar.gz: 6b14a49842eaf4c3e0fbae5acd28fdf32a5deb6cd42f769aada848226847180c4d3a67a9dcbc439e1a4855699b0ea694cb4c7b6ee173391ac841bd334ae44b6f
6
+ metadata.gz: e7f01438708076a283326c78b052ba954a42de4134d8d1d7e7c336c82ecd04c661f75dad3a0f9b1ffebe278f76ef229c98a3f2568801f82d94c94a50f399a2ef
7
+ data.tar.gz: 4f44c0e92eb9e565611772ba28d426025621c0517c4217004c3409192991a17498dd38165a6c55561a5347d2fcdf34f51b24101ad6de525604e35785e89efbc0
data/CHANGELOG.md CHANGED
@@ -1,3 +1,38 @@
1
+ ## 1.4.4 / 2022-12-13
2
+
3
+ * Address inefficient regular expression complexity with certain configurations of Rails::Html::Sanitizer.
4
+
5
+ Fixes CVE-2022-23517. See
6
+ [GHSA-5x79-w82f-gw8w](https://github.com/rails/rails-html-sanitizer/security/advisories/GHSA-5x79-w82f-gw8w)
7
+ for more information.
8
+
9
+ *Mike Dalessio*
10
+
11
+ * Address improper sanitization of data URIs.
12
+
13
+ Fixes CVE-2022-23518 and #135. See
14
+ [GHSA-mcvf-2q2m-x72m](https://github.com/rails/rails-html-sanitizer/security/advisories/GHSA-mcvf-2q2m-x72m)
15
+ for more information.
16
+
17
+ *Mike Dalessio*
18
+
19
+ * Address possible XSS vulnerability with certain configurations of Rails::Html::Sanitizer.
20
+
21
+ Fixes CVE-2022-23520. See
22
+ [GHSA-rrfc-7g8p-99q8](https://github.com/rails/rails-html-sanitizer/security/advisories/GHSA-rrfc-7g8p-99q8)
23
+ for more information.
24
+
25
+ *Mike Dalessio*
26
+
27
+ * Address possible XSS vulnerability with certain configurations of Rails::Html::Sanitizer.
28
+
29
+ Fixes CVE-2022-23519. See
30
+ [GHSA-9h9g-93gc-623h](https://github.com/rails/rails-html-sanitizer/security/advisories/GHSA-9h9g-93gc-623h)
31
+ for more information.
32
+
33
+ *Mike Dalessio*
34
+
35
+
1
36
  ## 1.4.3 / 2022-06-09
2
37
 
3
38
  * Address a possible XSS vulnerability with certain configurations of Rails::Html::Sanitizer.
@@ -1,7 +1,7 @@
1
1
  module Rails
2
2
  module Html
3
3
  class Sanitizer
4
- VERSION = "1.4.3"
4
+ VERSION = "1.4.4"
5
5
  end
6
6
  end
7
7
  end
@@ -141,25 +141,8 @@ 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
-
157
144
  def allowed_tags(options)
158
- if options[:tags]
159
- remove_safelist_tag_combinations(options[:tags])
160
- else
161
- self.class.allowed_tags
162
- end
145
+ options[:tags] || self.class.allowed_tags
163
146
  end
164
147
 
165
148
  def allowed_attributes(options)
@@ -61,9 +61,9 @@ module Rails
61
61
  end
62
62
 
63
63
  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)
67
67
  return CONTINUE
68
68
  end
69
69
  return CONTINUE if skip_node?(node)
@@ -139,15 +139,13 @@ module Rails
139
139
  end
140
140
 
141
141
  if Loofah::HTML5::SafeList::ATTR_VAL_IS_URI.include?(attr_name)
142
- # this block lifted nearly verbatim from HTML5 sanitization
143
- val_unescaped = CGI.unescapeHTML(attr_node.value).gsub(Loofah::HTML5::Scrub::CONTROL_CHARACTERS,'').downcase
144
- if val_unescaped =~ /^[a-z0-9][-+.a-z0-9]*:/ && ! Loofah::HTML5::SafeList::ALLOWED_PROTOCOLS.include?(val_unescaped.split(Loofah::HTML5::SafeList::PROTOCOL_SEPARATOR)[0])
145
- attr_node.remove
146
- end
142
+ return if Loofah::HTML5::Scrub.scrub_uri_attribute(attr_node)
147
143
  end
144
+
148
145
  if Loofah::HTML5::SafeList::SVG_ATTR_VAL_ALLOWS_REF.include?(attr_name)
149
- attr_node.value = attr_node.value.gsub(/url\s*\(\s*[^#\s][^)]+?\)/m, ' ') if attr_node.value
146
+ Loofah::HTML5::Scrub.scrub_attribute_that_allows_local_ref(attr_node)
150
147
  end
148
+
151
149
  if Loofah::HTML5::SafeList::SVG_ALLOW_LOCAL_HREF.include?(node.name) && attr_name == 'xlink:href' && attr_node.value =~ /^\s*[^#\s].*/m
152
150
  attr_node.remove
153
151
  end
@@ -54,7 +54,7 @@ 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
- expected = libxml_2_9_14_recovery? ? %{&lt;" hi} : %{ hi}
57
+ expected = libxml_2_9_14_recovery_lt? ? %{&lt;" hi} : %{ hi}
58
58
  assert_equal(expected, full_sanitize(input))
59
59
  end
60
60
 
@@ -77,19 +77,19 @@ class SanitizersTest < Minitest::Test
77
77
 
78
78
  def test_remove_unclosed_tags
79
79
  input = "This is <-- not\n a comment here."
80
- expected = libxml_2_9_14_recovery? ? %{This is &lt;-- not\n a comment here.} : %{This is }
80
+ expected = libxml_2_9_14_recovery_lt? ? %{This is &lt;-- not\n a comment here.} : %{This is }
81
81
  assert_equal(expected, full_sanitize(input))
82
82
  end
83
83
 
84
84
  def test_strip_cdata
85
85
  input = "This has a <![CDATA[<section>]]> here."
86
- expected = libxml_2_9_14_recovery? ? %{This has a &lt;![CDATA[]]&gt; here.} : %{This has a ]]&gt; here.}
86
+ expected = libxml_2_9_14_recovery_lt_bang? ? %{This has a &lt;![CDATA[]]&gt; here.} : %{This has a ]]&gt; here.}
87
87
  assert_equal(expected, full_sanitize(input))
88
88
  end
89
89
 
90
90
  def test_strip_unclosed_cdata
91
91
  input = "This has an unclosed <![CDATA[<section>]] here..."
92
- expected = libxml_2_9_14_recovery? ? %{This has an unclosed &lt;![CDATA[]] here...} : %{This has an unclosed ]] here...}
92
+ expected = libxml_2_9_14_recovery_lt_bang? ? %{This has an unclosed &lt;![CDATA[]] here...} : %{This has an unclosed ]] here...}
93
93
  assert_equal(expected, full_sanitize(input))
94
94
  end
95
95
 
@@ -458,13 +458,13 @@ class SanitizersTest < Minitest::Test
458
458
 
459
459
  def test_should_sanitize_cdata_section
460
460
  input = "<![CDATA[<span>section</span>]]>"
461
- expected = libxml_2_9_14_recovery? ? %{&lt;![CDATA[<span>section</span>]]&gt;} : %{section]]&gt;}
461
+ expected = libxml_2_9_14_recovery_lt_bang? ? %{&lt;![CDATA[<span>section</span>]]&gt;} : %{section]]&gt;}
462
462
  assert_sanitized(input, expected)
463
463
  end
464
464
 
465
465
  def test_should_sanitize_unterminated_cdata_section
466
466
  input = "<![CDATA[<span>neverending..."
467
- expected = libxml_2_9_14_recovery? ? %{&lt;![CDATA[<span>neverending...</span>} : %{neverending...}
467
+ expected = libxml_2_9_14_recovery_lt_bang? ? %{&lt;![CDATA[<span>neverending...</span>} : %{neverending...}
468
468
  assert_sanitized(input, expected)
469
469
  end
470
470
 
@@ -581,23 +581,124 @@ class SanitizersTest < Minitest::Test
581
581
  assert_equal("<div>text</div><b>text</b>", safe_list_sanitize("<div>text</div><!-- comment --><b>text</b>"))
582
582
  end
583
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) }
584
+ %w[text/plain text/css image/png image/gif image/jpeg].each do |mediatype|
585
+ define_method "test_mediatype_#{mediatype}_allowed" do
586
+ input = %Q(<img src="data:#{mediatype};base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4=">)
587
+ expected = input
588
+ actual = safe_list_sanitize(input)
589
+ assert_equal(expected, actual)
590
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)
591
+ input = %Q(<img src="DATA:#{mediatype};base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4=">)
592
+ expected = input
593
+ actual = safe_list_sanitize(input)
594
+ assert_equal(expected, actual)
595
+ end
596
+ end
597
+
598
+ def test_mediatype_text_html_disallowed
599
+ input = %q(<img src="data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4=">)
600
+ expected = %q(<img>)
601
+ actual = safe_list_sanitize(input)
602
+ assert_equal(expected, actual)
603
+
604
+ input = %q(<img src="DATA:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4=">)
605
+ expected = %q(<img>)
606
+ actual = safe_list_sanitize(input)
607
+ assert_equal(expected, actual)
608
+ end
609
+
610
+ def test_mediatype_image_svg_xml_disallowed
611
+ input = %q(<img src="data:image/svg+xml;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4=">)
612
+ expected = %q(<img>)
613
+ actual = safe_list_sanitize(input)
614
+ assert_equal(expected, actual)
615
+
616
+ input = %q(<img src="DATA:image/svg+xml;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4=">)
617
+ expected = %q(<img>)
618
+ actual = safe_list_sanitize(input)
619
+ assert_equal(expected, actual)
620
+ end
621
+
622
+ def test_mediatype_other_disallowed
623
+ input = %q(<a href="data:foo;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4=">foo</a>)
624
+ expected = %q(<a>foo</a>)
625
+ actual = safe_list_sanitize(input)
626
+ assert_equal(expected, actual)
627
+
628
+ input = %q(<a href="DATA:foo;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4=">foo</a>)
629
+ expected = %q(<a>foo</a>)
630
+ actual = safe_list_sanitize(input)
631
+ assert_equal(expected, actual)
632
+ end
633
+
634
+ def test_scrubbing_svg_attr_values_that_allow_ref
635
+ input = %Q(<div fill="yellow url(http://bad.com/) #fff">hey</div>)
636
+ expected = %Q(<div fill="yellow #fff">hey</div>)
637
+ actual = scope_allowed_attributes %w(fill) do
638
+ safe_list_sanitize(input)
599
639
  end
600
- refute_includes(sanitized, "style")
640
+
641
+ assert_equal(expected, actual)
642
+ end
643
+
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)
601
702
  end
602
703
 
603
704
  protected
@@ -657,11 +758,14 @@ protected
657
758
  end.join
658
759
  end
659
760
 
660
- def libxml_2_9_14_recovery?
761
+ def libxml_2_9_14_recovery_lt?
762
+ # changed in 2.9.14, see https://github.com/sparklemotion/nokogiri/releases/tag/v1.13.5
661
763
  Nokogiri.method(:uses_libxml?).arity == -1 && Nokogiri.uses_libxml?(">= 2.9.14")
662
764
  end
663
765
 
664
- def html5_mode?
665
- ::Loofah.respond_to?(:html5_mode?) && ::Loofah.html5_mode?
766
+ def libxml_2_9_14_recovery_lt_bang?
767
+ # changed in 2.9.14, see https://github.com/sparklemotion/nokogiri/releases/tag/v1.13.5
768
+ # then reverted in 2.10.0, see https://gitlab.gnome.org/GNOME/libxml2/-/issues/380
769
+ Nokogiri.method(:uses_libxml?).arity == -1 && Nokogiri.uses_libxml?("= 2.9.14")
666
770
  end
667
771
  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.3
4
+ version: 1.4.4
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: 2022-06-09 00:00:00.000000000 Z
12
+ date: 2022-12-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: loofah
@@ -17,14 +17,20 @@ dependencies:
17
17
  requirements:
18
18
  - - "~>"
19
19
  - !ruby/object:Gem::Version
20
- version: '2.3'
20
+ version: '2.19'
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.19.1
21
24
  type: :runtime
22
25
  prerelease: false
23
26
  version_requirements: !ruby/object:Gem::Requirement
24
27
  requirements:
25
28
  - - "~>"
26
29
  - !ruby/object:Gem::Version
27
- version: '2.3'
30
+ version: '2.19'
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 2.19.1
28
34
  - !ruby/object:Gem::Dependency
29
35
  name: bundler
30
36
  requirement: !ruby/object:Gem::Requirement
@@ -103,9 +109,9 @@ licenses:
103
109
  - MIT
104
110
  metadata:
105
111
  bug_tracker_uri: https://github.com/rails/rails-html-sanitizer/issues
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
112
+ changelog_uri: https://github.com/rails/rails-html-sanitizer/blob/v1.4.4/CHANGELOG.md
113
+ documentation_uri: https://www.rubydoc.info/gems/rails-html-sanitizer/1.4.4
114
+ source_code_uri: https://github.com/rails/rails-html-sanitizer/tree/v1.4.4
109
115
  post_install_message:
110
116
  rdoc_options: []
111
117
  require_paths:
@@ -121,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
121
127
  - !ruby/object:Gem::Version
122
128
  version: '0'
123
129
  requirements: []
124
- rubygems_version: 3.3.5
130
+ rubygems_version: 3.3.7
125
131
  signing_key:
126
132
  specification_version: 4
127
133
  summary: This gem is responsible to sanitize HTML fragments in Rails applications.