loofah 2.19.0 → 2.20.0

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: 3d59ed56910860de60170e919b3ab77b382f00eadc5d37518a7a395edabc8a4f
4
- data.tar.gz: d0ed6a2362ec8b366f4739a67c2197a24c45e0681cba6e5bd6b7b55617d492dc
3
+ metadata.gz: b06da35026008830bdcee25d54ccaf1cafb06cbb7ed92cd4fbbfd147b022c693
4
+ data.tar.gz: 67dd118c7d21f3bcb80b27b3c4e125907eacfc14f26c5ee1232b3f238eea9dbf
5
5
  SHA512:
6
- metadata.gz: dabaf4204cf846132d0b2962cef11534e3043ae8b2be39cbf23dea2fabc3722d83fba8805a5453fca6f2ec80f13c48c62726751f6acf06d3fdfd427297f07968
7
- data.tar.gz: 84d3442b65227346d62df8ea24ef0febe3212b1a1bdb61266f22cafc356467637f2a3a050d4c52672d55e081a3e040d2cb423961d571cf364978265398742f47
6
+ metadata.gz: 66a34115418e430e251bd599dd7529eeac2efd7d0c8795ac8001f810451fc871ef0a42fd1c767b78a90dc64d62323dadb1d9093d352e024785608ddafd43ec00
7
+ data.tar.gz: 31d10913e97432fb5a511019b22b6b9325b5c9e7e2cfc28aaf175fdb0ad62e9449c7879ff47f1fbca82ab1f36eec05751b7051c1eefcbdf0c6d04b60b592a45f
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.20.0 / 2023-04-01
4
+
5
+ ### Features
6
+
7
+ * Allow SVG attributes `color-profile`, `cursor`, `filter`, `marker`, and `mask`. [[#246](https://github.com/flavorjones/loofah/issues/246)]
8
+ * Allow SVG elements `altGlyph`, `cursor`, `feImage`, `pattern`, and `tref`. [[#246](https://github.com/flavorjones/loofah/issues/246)]
9
+ * Allow protocols `fax` and `modem`. [[#255](https://github.com/flavorjones/loofah/issues/255)] (Thanks, [@cjba7](https://github.com/cjba7)!)
10
+
11
+
12
+ ## 2.19.1 / 2022-12-13
13
+
14
+ ### Security
15
+
16
+ * Address CVE-2022-23514, inefficient regular expression complexity. See [GHSA-486f-hjj9-9vhh](https://github.com/flavorjones/loofah/security/advisories/GHSA-486f-hjj9-9vhh) for more information.
17
+ * Address CVE-2022-23515, improper neutralization of data URIs. See [GHSA-228g-948r-83gx](https://github.com/flavorjones/loofah/security/advisories/GHSA-228g-948r-83gx) for more information.
18
+ * Address CVE-2022-23516, uncontrolled recursion. See [GHSA-3x8r-x6xp-q4vm](https://github.com/flavorjones/loofah/security/advisories/GHSA-3x8r-x6xp-q4vm) for more information.
19
+
20
+
3
21
  ## 2.19.0 / 2022-09-14
4
22
 
5
23
  ### Features
@@ -181,16 +181,19 @@ module Loofah
181
181
 
182
182
  SVG_ELEMENTS = Set.new([
183
183
  "a",
184
+ "altGlyph",
184
185
  "animate",
185
186
  "animateColor",
186
187
  "animateMotion",
187
188
  "animateTransform",
188
189
  "circle",
189
190
  "clipPath",
191
+ "cursor",
190
192
  "defs",
191
193
  "desc",
192
194
  "ellipse",
193
195
  "feGaussianBlur",
196
+ "feImage",
194
197
  "filter",
195
198
  "font-face",
196
199
  "font-face-name",
@@ -207,6 +210,7 @@ module Loofah
207
210
  "missing-glyph",
208
211
  "mpath",
209
212
  "path",
213
+ "pattern",
210
214
  "polygon",
211
215
  "polyline",
212
216
  "radialGradient",
@@ -219,6 +223,7 @@ module Loofah
219
223
  "text",
220
224
  "textPath",
221
225
  "title",
226
+ "tref",
222
227
  "tspan",
223
228
  "use",
224
229
  ])
@@ -377,8 +382,10 @@ module Loofah
377
382
  "clip-rule",
378
383
  "color",
379
384
  "color-interpolation-filters",
385
+ "color-profile",
380
386
  "color-rendering",
381
387
  "content",
388
+ "cursor",
382
389
  "cx",
383
390
  "cy",
384
391
  "d",
@@ -391,6 +398,7 @@ module Loofah
391
398
  "fill",
392
399
  "fill-opacity",
393
400
  "fill-rule",
401
+ "filter",
394
402
  "filterRes",
395
403
  "filterUnits",
396
404
  "font-family",
@@ -416,12 +424,14 @@ module Loofah
416
424
  "keySplines",
417
425
  "keyTimes",
418
426
  "lang",
427
+ "marker",
419
428
  "marker-end",
420
429
  "marker-mid",
421
430
  "marker-start",
422
431
  "markerHeight",
423
432
  "markerUnits",
424
433
  "markerWidth",
434
+ "mask",
425
435
  "maskContentUnits",
426
436
  "maskUnits",
427
437
  "mathematical",
@@ -972,6 +982,7 @@ module Loofah
972
982
  "callto",
973
983
  "data",
974
984
  "ed2k",
985
+ "fax",
975
986
  "feed",
976
987
  "ftp",
977
988
  "gopher",
@@ -980,6 +991,7 @@ module Loofah
980
991
  "irc",
981
992
  "line",
982
993
  "mailto",
994
+ "modem",
983
995
  "news",
984
996
  "nntp",
985
997
  "rsync",
@@ -999,7 +1011,6 @@ module Loofah
999
1011
  "image/gif",
1000
1012
  "image/jpeg",
1001
1013
  "image/png",
1002
- "image/svg+xml",
1003
1014
  "text/css",
1004
1015
  "text/plain",
1005
1016
  ])
@@ -36,24 +36,13 @@ module Loofah
36
36
  end
37
37
 
38
38
  if SafeList::ATTR_VAL_IS_URI.include?(attr_name)
39
- # this block lifted nearly verbatim from HTML5 sanitization
40
- val_unescaped = CGI.unescapeHTML(attr_node.value).gsub(CONTROL_CHARACTERS, "").downcase
41
- if val_unescaped =~ /^[a-z0-9][-+.a-z0-9]*:/ && !SafeList::ALLOWED_PROTOCOLS.include?(val_unescaped.split(SafeList::PROTOCOL_SEPARATOR)[0])
42
- attr_node.remove
43
- next
44
- elsif val_unescaped.split(SafeList::PROTOCOL_SEPARATOR)[0] == "data"
45
- # permit only allowed data mediatypes
46
- mediatype = val_unescaped.split(SafeList::PROTOCOL_SEPARATOR)[1]
47
- mediatype, _ = mediatype.split(";")[0..1] if mediatype
48
- if mediatype && !SafeList::ALLOWED_URI_DATA_MEDIATYPES.include?(mediatype)
49
- attr_node.remove
50
- next
51
- end
52
- end
39
+ next if scrub_uri_attribute(attr_node)
53
40
  end
41
+
54
42
  if SafeList::SVG_ATTR_VAL_ALLOWS_REF.include?(attr_name)
55
- attr_node.value = attr_node.value.gsub(/url\s*\(\s*[^#\s][^)]+?\)/m, " ") if attr_node.value
43
+ scrub_attribute_that_allows_local_ref(attr_node)
56
44
  end
45
+
57
46
  if SafeList::SVG_ALLOW_LOCAL_HREF.include?(node.name) && attr_name == "xlink:href" && attr_node.value =~ /^\s*[^#\s].*/m
58
47
  attr_node.remove
59
48
  next
@@ -127,6 +116,47 @@ module Loofah
127
116
  Crass::Parser.stringify(sanitized_tree)
128
117
  end
129
118
 
119
+ def scrub_attribute_that_allows_local_ref(attr_node)
120
+ return unless attr_node.value
121
+
122
+ nodes = Crass::Parser.new(attr_node.value).parse_component_values
123
+
124
+ values = nodes.map do |node|
125
+ case node[:node]
126
+ when :url
127
+ if node[:value].start_with?("#")
128
+ node[:raw]
129
+ else
130
+ nil
131
+ end
132
+ when :hash, :ident, :string
133
+ node[:raw]
134
+ else
135
+ nil
136
+ end
137
+ end.compact
138
+
139
+ attr_node.value = values.join(" ")
140
+ end
141
+
142
+ def scrub_uri_attribute(attr_node)
143
+ # this block lifted nearly verbatim from HTML5 sanitization
144
+ val_unescaped = CGI.unescapeHTML(attr_node.value).gsub(CONTROL_CHARACTERS, "").downcase
145
+ if val_unescaped =~ /^[a-z0-9][-+.a-z0-9]*:/ && !SafeList::ALLOWED_PROTOCOLS.include?(val_unescaped.split(SafeList::PROTOCOL_SEPARATOR)[0])
146
+ attr_node.remove
147
+ return true
148
+ elsif val_unescaped.split(SafeList::PROTOCOL_SEPARATOR)[0] == "data"
149
+ # permit only allowed data mediatypes
150
+ mediatype = val_unescaped.split(SafeList::PROTOCOL_SEPARATOR)[1]
151
+ mediatype, _ = mediatype.split(";")[0..1] if mediatype
152
+ if mediatype && !SafeList::ALLOWED_URI_DATA_MEDIATYPES.include?(mediatype)
153
+ attr_node.remove
154
+ return true
155
+ end
156
+ end
157
+ false
158
+ end
159
+
130
160
  #
131
161
  # libxml2 >= 2.9.2 fails to escape comments within some attributes.
132
162
  #
@@ -152,6 +182,46 @@ module Loofah
152
182
  end.force_encoding(encoding)
153
183
  end
154
184
  end
185
+
186
+ def cdata_needs_escaping?(node)
187
+ # Nokogiri's HTML4 parser on JRuby doesn't flag the child of a `style` or `script` tag as cdata, but it acts that way
188
+ node.cdata? || (Nokogiri.jruby? && node.text? && (node.parent.name == "style" || node.parent.name == "script"))
189
+ end
190
+
191
+ def cdata_escape(node)
192
+ escaped_text = escape_tags(node.text)
193
+ if Nokogiri.jruby?
194
+ node.document.create_text_node(escaped_text)
195
+ else
196
+ node.document.create_cdata(escaped_text)
197
+ end
198
+ end
199
+
200
+ TABLE_FOR_ESCAPE_HTML__ = {
201
+ '<' => '&lt;',
202
+ '>' => '&gt;',
203
+ '&' => '&amp;',
204
+ }
205
+
206
+ def escape_tags(string)
207
+ # modified version of CGI.escapeHTML from ruby 3.1
208
+ enc = string.encoding
209
+ unless enc.ascii_compatible?
210
+ if enc.dummy?
211
+ origenc = enc
212
+ enc = Encoding::Converter.asciicompat_encoding(enc)
213
+ string = enc ? string.encode(enc) : string.b
214
+ end
215
+ table = Hash[TABLE_FOR_ESCAPE_HTML__.map {|pair|pair.map {|s|s.encode(enc)}}]
216
+ string = string.gsub(/#{"[<>&]".encode(enc)}/, table)
217
+ string.encode!(origenc) if origenc
218
+ string
219
+ else
220
+ string = string.b
221
+ string.gsub!(/[<>&]/, TABLE_FOR_ESCAPE_HTML__)
222
+ string.force_encoding(enc)
223
+ end
224
+ end
155
225
  end
156
226
  end
157
227
  end
@@ -108,6 +108,10 @@ module Loofah
108
108
  return Scrubber::CONTINUE
109
109
  end
110
110
  when Nokogiri::XML::Node::TEXT_NODE, Nokogiri::XML::Node::CDATA_SECTION_NODE
111
+ if HTML5::Scrub.cdata_needs_escaping?(node)
112
+ node.before(HTML5::Scrub.cdata_escape(node))
113
+ return Scrubber::STOP
114
+ end
111
115
  return Scrubber::CONTINUE
112
116
  end
113
117
  Scrubber::STOP
@@ -100,13 +100,9 @@ module Loofah
100
100
 
101
101
  def scrub(node)
102
102
  return CONTINUE if html5lib_sanitize(node) == CONTINUE
103
- if node.children.length == 1 && node.children.first.cdata?
104
- sanitized_text = Loofah.fragment(node.children.first.to_html).scrub!(:strip).to_html
105
- node.before Nokogiri::XML::Text.new(sanitized_text, node.document)
106
- else
107
- node.before node.children
108
- end
103
+ node.before(node.children)
109
104
  node.remove
105
+ return STOP
110
106
  end
111
107
  end
112
108
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  module Loofah
3
3
  # The version of Loofah you are using
4
- VERSION = "2.19.0"
4
+ VERSION = "2.20.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: loofah
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.19.0
4
+ version: 2.20.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Dalessio
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-09-14 00:00:00.000000000 Z
12
+ date: 2023-04-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: crass
@@ -115,20 +115,6 @@ dependencies:
115
115
  - - "<"
116
116
  - !ruby/object:Gem::Version
117
117
  version: '7'
118
- - !ruby/object:Gem::Dependency
119
- name: rr
120
- requirement: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - "~>"
123
- - !ruby/object:Gem::Version
124
- version: 1.2.0
125
- type: :development
126
- prerelease: false
127
- version_requirements: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - "~>"
130
- - !ruby/object:Gem::Version
131
- version: 1.2.0
132
118
  - !ruby/object:Gem::Dependency
133
119
  name: rubocop
134
120
  requirement: !ruby/object:Gem::Requirement
@@ -199,7 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
199
185
  - !ruby/object:Gem::Version
200
186
  version: '0'
201
187
  requirements: []
202
- rubygems_version: 3.3.7
188
+ rubygems_version: 3.4.10
203
189
  signing_key:
204
190
  specification_version: 4
205
191
  summary: Loofah is a general library for manipulating and transforming HTML/XML documents