loofah 2.2.3 → 2.3.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of loofah might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +37 -0
- data/Gemfile +3 -3
- data/Manifest.txt +2 -1
- data/README.md +6 -13
- data/Rakefile +22 -20
- data/lib/loofah.rb +15 -15
- data/lib/loofah/helpers.rb +13 -3
- data/lib/loofah/html5/safelist.rb +796 -0
- data/lib/loofah/html5/scrub.rb +14 -14
- data/lib/loofah/scrubbers.rb +1 -1
- data/test/html5/test_sanitizer.rb +36 -17
- data/test/html5/test_scrub.rb +10 -0
- data/test/integration/test_ad_hoc.rb +41 -25
- data/test/unit/test_helpers.rb +4 -4
- metadata +37 -43
- data/lib/loofah/html5/whitelist.rb +0 -186
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1196afab25d29644d1961e4516ac317a2c38dee3295f35354c468e6a9318fa55
|
4
|
+
data.tar.gz: 2e07ff641edb37d2b0dce2933288da4667d4b680a586912af9c171db7dfb0a63
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 37ac2cdb0d136da417cff62e3845c5b71769f044d8150c636a549dc9ca4cf98bcef4c6d2b6e653eff56922b95d812ed39310a406c49366c14791456ca905e8fe
|
7
|
+
data.tar.gz: 0fa3cdd75a3d2950801a1cfe7f8d4cad6bb73bbec67d24ba25980c09a565f6c95c5d664c1789ccd62486d1917c685a5b0f762cc073a054bbb0f02fb0222688f0
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,42 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 2.3.1 / 2019-10-22
|
4
|
+
|
5
|
+
### Security
|
6
|
+
|
7
|
+
Address CVE-2019-15587: Unsanitized JavaScript may occur in sanitized output when a crafted SVG element is republished.
|
8
|
+
|
9
|
+
This CVE's public notice is at https://github.com/flavorjones/loofah/issues/171
|
10
|
+
|
11
|
+
|
12
|
+
## 2.3.0 / 2019-09-28
|
13
|
+
|
14
|
+
### Features
|
15
|
+
|
16
|
+
* Expand set of allowed protocols to include `tel:` and `line:`. [#104, #147]
|
17
|
+
* Expand set of allowed CSS functions. [related to #122]
|
18
|
+
* Allow greater precision in shorthand CSS values. [#149] (Thanks, @danfstucky!)
|
19
|
+
* Allow CSS property `list-style` [#162] (Thanks, @jaredbeck!)
|
20
|
+
* Allow CSS keywords `thick` and `thin` [#168] (Thanks, @georgeclaghorn!)
|
21
|
+
* Allow HTML property `contenteditable` [#167] (Thanks, @andreynering!)
|
22
|
+
|
23
|
+
|
24
|
+
### Bug fixes
|
25
|
+
|
26
|
+
* CSS hex values are no longer limited to lowercase hex. Previously uppercase hex were scrubbed. [#165] (Thanks, @asok!)
|
27
|
+
|
28
|
+
|
29
|
+
### Deprecations / Name Changes
|
30
|
+
|
31
|
+
The following method and constants are hereby deprecated, and will be completely removed in a future release:
|
32
|
+
|
33
|
+
* Deprecate `Loofah::Helpers::ActionView.white_list_sanitizer`, please use `Loofah::Helpers::ActionView.safe_list_sanitizer` instead.
|
34
|
+
* Deprecate `Loofah::Helpers::ActionView::WhiteListSanitizer`, please use `Loofah::Helpers::ActionView::SafeListSanitizer` instead.
|
35
|
+
* Deprecate `Loofah::HTML5::WhiteList`, please use `Loofah::HTML5::SafeList` instead.
|
36
|
+
|
37
|
+
Thanks to @JuanitoFatas for submitting these changes in #164 and for making the language used in Loofah more inclusive.
|
38
|
+
|
39
|
+
|
3
40
|
## 2.2.3 / 2018-10-30
|
4
41
|
|
5
42
|
### Security
|
data/Gemfile
CHANGED
@@ -15,8 +15,8 @@ gem "hoe-gemspec", ">=0", :group => [:development, :test]
|
|
15
15
|
gem "hoe-debugging", ">=0", :group => [:development, :test]
|
16
16
|
gem "hoe-bundler", ">=0", :group => [:development, :test]
|
17
17
|
gem "hoe-git", ">=0", :group => [:development, :test]
|
18
|
-
gem "concourse", ">=0.
|
19
|
-
gem "rdoc", "
|
20
|
-
gem "hoe", "~>3.
|
18
|
+
gem "concourse", ">=0.26.0", :group => [:development, :test]
|
19
|
+
gem "rdoc", ">=4.0", "<7", :group => [:development, :test]
|
20
|
+
gem "hoe", "~>3.17", :group => [:development, :test]
|
21
21
|
|
22
22
|
# vim: syntax=ruby
|
data/Manifest.txt
CHANGED
@@ -16,8 +16,8 @@ lib/loofah/helpers.rb
|
|
16
16
|
lib/loofah/html/document.rb
|
17
17
|
lib/loofah/html/document_fragment.rb
|
18
18
|
lib/loofah/html5/libxml2_workarounds.rb
|
19
|
+
lib/loofah/html5/safelist.rb
|
19
20
|
lib/loofah/html5/scrub.rb
|
20
|
-
lib/loofah/html5/whitelist.rb
|
21
21
|
lib/loofah/instance_methods.rb
|
22
22
|
lib/loofah/metahelpers.rb
|
23
23
|
lib/loofah/scrubber.rb
|
@@ -28,6 +28,7 @@ test/assets/msword.html
|
|
28
28
|
test/assets/testdata_sanitizer_tests1.dat
|
29
29
|
test/helper.rb
|
30
30
|
test/html5/test_sanitizer.rb
|
31
|
+
test/html5/test_scrub.rb
|
31
32
|
test/integration/test_ad_hoc.rb
|
32
33
|
test/integration/test_helpers.rb
|
33
34
|
test/integration/test_html.rb
|
data/README.md
CHANGED
@@ -8,29 +8,22 @@
|
|
8
8
|
|
9
9
|
|System|Status|
|
10
10
|
|--|--|
|
11
|
-
| Concourse | [![Concourse CI](https://ci.nokogiri.org/api/v1/teams/nokogiri-core/pipelines/loofah/jobs/ruby-2.5/badge)](https://ci.nokogiri.org/teams/nokogiri-core/pipelines/loofah?groups=master) |
|
11
|
+
| Concourse CI | [![Concourse CI](https://ci.nokogiri.org/api/v1/teams/nokogiri-core/pipelines/loofah/jobs/ruby-2.5/badge)](https://ci.nokogiri.org/teams/nokogiri-core/pipelines/loofah?groups=master) |
|
12
12
|
| Code Climate | [![Code Climate](https://codeclimate.com/github/flavorjones/loofah.svg)](https://codeclimate.com/github/flavorjones/loofah) |
|
13
|
-
| Version Eye | [![Version Eye](https://www.versioneye.com/ruby/loofah/badge.png)](https://www.versioneye.com/ruby/loofah) |
|
14
13
|
|
15
14
|
|
16
15
|
## Description
|
17
16
|
|
18
|
-
Loofah is a general library for manipulating and transforming HTML/XML
|
19
|
-
documents and fragments. It's built on top of Nokogiri and libxml2, so
|
20
|
-
it's fast and has a nice API.
|
17
|
+
Loofah is a general library for manipulating and transforming HTML/XML documents and fragments, built on top of Nokogiri.
|
21
18
|
|
22
|
-
Loofah excels at HTML sanitization (XSS prevention). It includes some
|
23
|
-
nice HTML sanitizers, which are based on HTML5lib's whitelist, so it
|
24
|
-
most likely won't make your codes less secure. (These statements have
|
25
|
-
not been evaluated by Netexperts.)
|
19
|
+
Loofah excels at HTML sanitization (XSS prevention). It includes some nice HTML sanitizers, which are based on HTML5lib's safelist, so it most likely won't make your codes less secure. (These statements have not been evaluated by Netexperts.)
|
26
20
|
|
27
|
-
ActiveRecord extensions for sanitization are available in the
|
28
|
-
[`loofah-activerecord` gem](https://github.com/flavorjones/loofah-activerecord).
|
21
|
+
ActiveRecord extensions for sanitization are available in the [`loofah-activerecord` gem](https://github.com/flavorjones/loofah-activerecord).
|
29
22
|
|
30
23
|
|
31
24
|
## Features
|
32
25
|
|
33
|
-
* Easily write custom scrubbers for HTML/XML leveraging the sweetness of Nokogiri (and HTML5lib's
|
26
|
+
* Easily write custom scrubbers for HTML/XML leveraging the sweetness of Nokogiri (and HTML5lib's safelists).
|
34
27
|
* Common HTML sanitizing tasks are built-in:
|
35
28
|
* _Strip_ unsafe tags, leaving behind only the inner text.
|
36
29
|
* _Prune_ unsafe tags and their subtrees, removing all traces that they ever existed.
|
@@ -222,7 +215,7 @@ Loofah.xml_document(File.read('plague.xml')).scrub!(bring_out_your_dead)
|
|
222
215
|
=== Built-In HTML Scrubbers
|
223
216
|
|
224
217
|
Loofah comes with a set of sanitizing scrubbers that use HTML5lib's
|
225
|
-
|
218
|
+
safelist algorithm:
|
226
219
|
|
227
220
|
``` ruby
|
228
221
|
doc.scrub!(:strip) # replaces unknown/unsafe tags with their inner text
|
data/Rakefile
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
require
|
2
|
-
|
3
|
-
require
|
4
|
-
require 'concourse'
|
1
|
+
require "rubygems"
|
2
|
+
require "hoe"
|
3
|
+
require "concourse"
|
5
4
|
|
6
5
|
Hoe.plugin :git
|
7
6
|
Hoe.plugin :gemspec
|
@@ -13,22 +12,22 @@ Hoe.spec "loofah" do
|
|
13
12
|
developer "Bryan Helmkamp", "bryan@brynary.com"
|
14
13
|
|
15
14
|
self.extra_rdoc_files = FileList["*.md"]
|
16
|
-
self.history_file
|
17
|
-
self.readme_file
|
18
|
-
self.license
|
15
|
+
self.history_file = "CHANGELOG.md"
|
16
|
+
self.readme_file = "README.md"
|
17
|
+
self.license "MIT"
|
19
18
|
|
20
|
-
extra_deps
|
21
|
-
extra_deps
|
19
|
+
extra_deps << ["nokogiri", ">=1.5.9"]
|
20
|
+
extra_deps << ["crass", "~> 1.0.2"]
|
22
21
|
|
23
|
-
extra_dev_deps << ["rake", "
|
22
|
+
extra_dev_deps << ["rake", "~> 12.3"]
|
24
23
|
extra_dev_deps << ["minitest", "~>2.2"]
|
25
24
|
extra_dev_deps << ["rr", "~>1.2.0"]
|
26
|
-
extra_dev_deps << ["json", "
|
27
|
-
extra_dev_deps << ["hoe-gemspec", "
|
28
|
-
extra_dev_deps << ["hoe-debugging", "
|
29
|
-
extra_dev_deps << ["hoe-bundler", "
|
30
|
-
extra_dev_deps << ["hoe-git", "
|
31
|
-
extra_dev_deps << ["concourse", ">=0.
|
25
|
+
extra_dev_deps << ["json", "~> 2.2.0"]
|
26
|
+
extra_dev_deps << ["hoe-gemspec", "~> 1.0"]
|
27
|
+
extra_dev_deps << ["hoe-debugging", "~> 2.0"]
|
28
|
+
extra_dev_deps << ["hoe-bundler", "~> 1.5"]
|
29
|
+
extra_dev_deps << ["hoe-git", "~> 1.6"]
|
30
|
+
extra_dev_deps << ["concourse", ">=0.26.0"]
|
32
31
|
end
|
33
32
|
|
34
33
|
task :gemspec do
|
@@ -71,9 +70,12 @@ task :doc_upload_to_rubyforge => :docs do
|
|
71
70
|
end
|
72
71
|
end
|
73
72
|
|
74
|
-
desc "generate
|
75
|
-
task :
|
76
|
-
load "tasks/generate-
|
73
|
+
desc "generate safelists from W3C specifications"
|
74
|
+
task :generate_safelists do
|
75
|
+
load "tasks/generate-safelists"
|
77
76
|
end
|
78
77
|
|
79
|
-
Concourse.new("loofah")
|
78
|
+
Concourse.new("loofah", fly_target: "ci") do |c|
|
79
|
+
c.add_pipeline "loofah", "loofah.yml"
|
80
|
+
c.add_pipeline "loofah-pr", "loofah-pr.yml"
|
81
|
+
end
|
data/lib/loofah.rb
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))
|
2
2
|
|
3
|
-
require
|
3
|
+
require "nokogiri"
|
4
4
|
|
5
|
-
require
|
6
|
-
require
|
5
|
+
require "loofah/metahelpers"
|
6
|
+
require "loofah/elements"
|
7
7
|
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
8
|
+
require "loofah/html5/safelist"
|
9
|
+
require "loofah/html5/libxml2_workarounds"
|
10
|
+
require "loofah/html5/scrub"
|
11
11
|
|
12
|
-
require
|
13
|
-
require
|
12
|
+
require "loofah/scrubber"
|
13
|
+
require "loofah/scrubbers"
|
14
14
|
|
15
|
-
require
|
16
|
-
require
|
17
|
-
require
|
18
|
-
require
|
19
|
-
require
|
15
|
+
require "loofah/instance_methods"
|
16
|
+
require "loofah/xml/document"
|
17
|
+
require "loofah/xml/document_fragment"
|
18
|
+
require "loofah/html/document"
|
19
|
+
require "loofah/html/document_fragment"
|
20
20
|
|
21
21
|
# == Strings and IO Objects as Input
|
22
22
|
#
|
@@ -28,7 +28,7 @@ require 'loofah/html/document_fragment'
|
|
28
28
|
#
|
29
29
|
module Loofah
|
30
30
|
# The version of Loofah you are using
|
31
|
-
VERSION =
|
31
|
+
VERSION = "2.3.1"
|
32
32
|
|
33
33
|
class << self
|
34
34
|
# Shortcut for Loofah::HTML::Document.parse
|
@@ -77,7 +77,7 @@ module Loofah
|
|
77
77
|
|
78
78
|
# A helper to remove extraneous whitespace from text-ified HTML
|
79
79
|
def remove_extraneous_whitespace(string)
|
80
|
-
string.gsub(/\n\s*\n\s*\n/,"\n\n")
|
80
|
+
string.gsub(/\n\s*\n\s*\n/, "\n\n")
|
81
81
|
end
|
82
82
|
end
|
83
83
|
end
|
data/lib/loofah/helpers.rb
CHANGED
@@ -46,8 +46,13 @@ module Loofah
|
|
46
46
|
@full_sanitizer ||= ::Loofah::Helpers::ActionView::FullSanitizer.new
|
47
47
|
end
|
48
48
|
|
49
|
+
def safe_list_sanitizer
|
50
|
+
@safe_list_sanitizer ||= ::Loofah::Helpers::ActionView::SafeListSanitizer.new
|
51
|
+
end
|
52
|
+
|
49
53
|
def white_list_sanitizer
|
50
|
-
|
54
|
+
warn "warning: white_list_sanitizer is deprecated, please use safe_list_sanitizer instead."
|
55
|
+
safe_list_sanitizer
|
51
56
|
end
|
52
57
|
end
|
53
58
|
|
@@ -73,13 +78,13 @@ module Loofah
|
|
73
78
|
#
|
74
79
|
# To use by default, call this in an application initializer:
|
75
80
|
#
|
76
|
-
# ActionView::Helpers::SanitizeHelper.
|
81
|
+
# ActionView::Helpers::SanitizeHelper.safe_list_sanitizer = ::Loofah::Helpers::ActionView::SafeListSanitizer.new
|
77
82
|
#
|
78
83
|
# Or, to generally opt-in to Loofah's view sanitizers:
|
79
84
|
#
|
80
85
|
# Loofah::Helpers::ActionView.set_as_default_sanitizer
|
81
86
|
#
|
82
|
-
class
|
87
|
+
class SafeListSanitizer
|
83
88
|
def sanitize html, *args
|
84
89
|
Loofah::Helpers.sanitize html
|
85
90
|
end
|
@@ -88,6 +93,11 @@ module Loofah
|
|
88
93
|
Loofah::Helpers.sanitize_css style_string
|
89
94
|
end
|
90
95
|
end
|
96
|
+
|
97
|
+
WhiteListSanitizer = SafeListSanitizer
|
98
|
+
if Object.respond_to?(:deprecate_constant)
|
99
|
+
deprecate_constant :WhiteListSanitizer
|
100
|
+
end
|
91
101
|
end
|
92
102
|
end
|
93
103
|
end
|
@@ -0,0 +1,796 @@
|
|
1
|
+
require "set"
|
2
|
+
|
3
|
+
module Loofah
|
4
|
+
module HTML5 # :nodoc:
|
5
|
+
#
|
6
|
+
# HTML safelist lifted from HTML5lib sanitizer code:
|
7
|
+
#
|
8
|
+
# http://code.google.com/p/html5lib/
|
9
|
+
#
|
10
|
+
# <html5_license>
|
11
|
+
#
|
12
|
+
# Copyright (c) 2006-2008 The Authors
|
13
|
+
#
|
14
|
+
# Contributors:
|
15
|
+
# James Graham - jg307@cam.ac.uk
|
16
|
+
# Anne van Kesteren - annevankesteren@gmail.com
|
17
|
+
# Lachlan Hunt - lachlan.hunt@lachy.id.au
|
18
|
+
# Matt McDonald - kanashii@kanashii.ca
|
19
|
+
# Sam Ruby - rubys@intertwingly.net
|
20
|
+
# Ian Hickson (Google) - ian@hixie.ch
|
21
|
+
# Thomas Broyer - t.broyer@ltgt.net
|
22
|
+
# Jacques Distler - distler@golem.ph.utexas.edu
|
23
|
+
# Henri Sivonen - hsivonen@iki.fi
|
24
|
+
# The Mozilla Foundation (contributions from Henri Sivonen since 2008)
|
25
|
+
#
|
26
|
+
# Permission is hereby granted, free of charge, to any person
|
27
|
+
# obtaining a copy of this software and associated documentation
|
28
|
+
# files (the "Software"), to deal in the Software without
|
29
|
+
# restriction, including without limitation the rights to use, copy,
|
30
|
+
# modify, merge, publish, distribute, sublicense, and/or sell copies
|
31
|
+
# of the Software, and to permit persons to whom the Software is
|
32
|
+
# furnished to do so, subject to the following conditions:
|
33
|
+
#
|
34
|
+
# The above copyright notice and this permission notice shall be
|
35
|
+
# included in all copies or substantial portions of the Software.
|
36
|
+
#
|
37
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
38
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
39
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
40
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
41
|
+
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
42
|
+
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
43
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
44
|
+
# DEALINGS IN THE SOFTWARE.
|
45
|
+
#
|
46
|
+
# </html5_license>
|
47
|
+
module SafeList
|
48
|
+
ACCEPTABLE_ELEMENTS = Set.new([
|
49
|
+
"a",
|
50
|
+
"abbr",
|
51
|
+
"acronym",
|
52
|
+
"address",
|
53
|
+
"area",
|
54
|
+
"article",
|
55
|
+
"aside",
|
56
|
+
"audio",
|
57
|
+
"b",
|
58
|
+
"bdi",
|
59
|
+
"bdo",
|
60
|
+
"big",
|
61
|
+
"blockquote",
|
62
|
+
"br",
|
63
|
+
"button",
|
64
|
+
"canvas",
|
65
|
+
"caption",
|
66
|
+
"center",
|
67
|
+
"cite",
|
68
|
+
"code",
|
69
|
+
"col",
|
70
|
+
"colgroup",
|
71
|
+
"command",
|
72
|
+
"datalist",
|
73
|
+
"dd",
|
74
|
+
"del",
|
75
|
+
"details",
|
76
|
+
"dfn",
|
77
|
+
"dir",
|
78
|
+
"div",
|
79
|
+
"dl",
|
80
|
+
"dt",
|
81
|
+
"em",
|
82
|
+
"fieldset",
|
83
|
+
"figcaption",
|
84
|
+
"figure",
|
85
|
+
"font",
|
86
|
+
"footer",
|
87
|
+
"form",
|
88
|
+
"h1",
|
89
|
+
"h2",
|
90
|
+
"h3",
|
91
|
+
"h4",
|
92
|
+
"h5",
|
93
|
+
"h6",
|
94
|
+
"header",
|
95
|
+
"hr",
|
96
|
+
"i",
|
97
|
+
"img",
|
98
|
+
"input",
|
99
|
+
"ins",
|
100
|
+
"kbd",
|
101
|
+
"label",
|
102
|
+
"legend",
|
103
|
+
"li",
|
104
|
+
"main",
|
105
|
+
"map",
|
106
|
+
"mark",
|
107
|
+
"menu",
|
108
|
+
"meter",
|
109
|
+
"nav",
|
110
|
+
"ol",
|
111
|
+
"optgroup",
|
112
|
+
"option",
|
113
|
+
"output",
|
114
|
+
"p",
|
115
|
+
"pre",
|
116
|
+
"q",
|
117
|
+
"s",
|
118
|
+
"samp",
|
119
|
+
"section",
|
120
|
+
"select",
|
121
|
+
"small",
|
122
|
+
"span",
|
123
|
+
"strike",
|
124
|
+
"strong",
|
125
|
+
"sub",
|
126
|
+
"summary",
|
127
|
+
"sup",
|
128
|
+
"table",
|
129
|
+
"tbody",
|
130
|
+
"td",
|
131
|
+
"textarea",
|
132
|
+
"tfoot",
|
133
|
+
"th",
|
134
|
+
"thead",
|
135
|
+
"time",
|
136
|
+
"tr",
|
137
|
+
"tt",
|
138
|
+
"u",
|
139
|
+
"ul",
|
140
|
+
"var",
|
141
|
+
"video",
|
142
|
+
])
|
143
|
+
|
144
|
+
MATHML_ELEMENTS = Set.new([
|
145
|
+
"annotation",
|
146
|
+
"annotation-xml",
|
147
|
+
"maction",
|
148
|
+
"math",
|
149
|
+
"merror",
|
150
|
+
"mfenced",
|
151
|
+
"mfrac",
|
152
|
+
"mi",
|
153
|
+
"mmultiscripts",
|
154
|
+
"mn",
|
155
|
+
"mo",
|
156
|
+
"mover",
|
157
|
+
"mpadded",
|
158
|
+
"mphantom",
|
159
|
+
"mprescripts",
|
160
|
+
"mroot",
|
161
|
+
"mrow",
|
162
|
+
"mspace",
|
163
|
+
"msqrt",
|
164
|
+
"mstyle",
|
165
|
+
"msub",
|
166
|
+
"msubsup",
|
167
|
+
"msup",
|
168
|
+
"mtable",
|
169
|
+
"mtd",
|
170
|
+
"mtext",
|
171
|
+
"mtr",
|
172
|
+
"munder",
|
173
|
+
"munderover",
|
174
|
+
"none",
|
175
|
+
"semantics",
|
176
|
+
])
|
177
|
+
|
178
|
+
SVG_ELEMENTS = Set.new([
|
179
|
+
"a",
|
180
|
+
"animate",
|
181
|
+
"animateColor",
|
182
|
+
"animateMotion",
|
183
|
+
"animateTransform",
|
184
|
+
"circle",
|
185
|
+
"clipPath",
|
186
|
+
"defs",
|
187
|
+
"desc",
|
188
|
+
"ellipse",
|
189
|
+
"feGaussianBlur",
|
190
|
+
"filter",
|
191
|
+
"font-face",
|
192
|
+
"font-face-name",
|
193
|
+
"font-face-src",
|
194
|
+
"foreignObject",
|
195
|
+
"g",
|
196
|
+
"glyph",
|
197
|
+
"hkern",
|
198
|
+
"line",
|
199
|
+
"linearGradient",
|
200
|
+
"marker",
|
201
|
+
"mask",
|
202
|
+
"metadata",
|
203
|
+
"missing-glyph",
|
204
|
+
"mpath",
|
205
|
+
"path",
|
206
|
+
"polygon",
|
207
|
+
"polyline",
|
208
|
+
"radialGradient",
|
209
|
+
"rect",
|
210
|
+
"set",
|
211
|
+
"stop",
|
212
|
+
"svg",
|
213
|
+
"switch",
|
214
|
+
"symbol",
|
215
|
+
"text",
|
216
|
+
"textPath",
|
217
|
+
"title",
|
218
|
+
"tspan",
|
219
|
+
"use",
|
220
|
+
])
|
221
|
+
|
222
|
+
ACCEPTABLE_ATTRIBUTES = Set.new([
|
223
|
+
"abbr",
|
224
|
+
"accept",
|
225
|
+
"accept-charset",
|
226
|
+
"accesskey",
|
227
|
+
"action",
|
228
|
+
"align",
|
229
|
+
"alt",
|
230
|
+
"axis",
|
231
|
+
"border",
|
232
|
+
"cellpadding",
|
233
|
+
"cellspacing",
|
234
|
+
"char",
|
235
|
+
"charoff",
|
236
|
+
"charset",
|
237
|
+
"checked",
|
238
|
+
"cite",
|
239
|
+
"class",
|
240
|
+
"clear",
|
241
|
+
"color",
|
242
|
+
"cols",
|
243
|
+
"colspan",
|
244
|
+
"compact",
|
245
|
+
"contenteditable",
|
246
|
+
"coords",
|
247
|
+
"datetime",
|
248
|
+
"dir",
|
249
|
+
"disabled",
|
250
|
+
"enctype",
|
251
|
+
"for",
|
252
|
+
"frame",
|
253
|
+
"headers",
|
254
|
+
"height",
|
255
|
+
"href",
|
256
|
+
"hreflang",
|
257
|
+
"hspace",
|
258
|
+
"id",
|
259
|
+
"ismap",
|
260
|
+
"label",
|
261
|
+
"lang",
|
262
|
+
"longdesc",
|
263
|
+
"loop",
|
264
|
+
"loopcount",
|
265
|
+
"loopend",
|
266
|
+
"loopstart",
|
267
|
+
"maxlength",
|
268
|
+
"media",
|
269
|
+
"method",
|
270
|
+
"multiple",
|
271
|
+
"name",
|
272
|
+
"nohref",
|
273
|
+
"noshade",
|
274
|
+
"nowrap",
|
275
|
+
"poster",
|
276
|
+
"preload",
|
277
|
+
"prompt",
|
278
|
+
"readonly",
|
279
|
+
"rel",
|
280
|
+
"rev",
|
281
|
+
"rows",
|
282
|
+
"rowspan",
|
283
|
+
"rules",
|
284
|
+
"scope",
|
285
|
+
"selected",
|
286
|
+
"shape",
|
287
|
+
"size",
|
288
|
+
"span",
|
289
|
+
"src",
|
290
|
+
"start",
|
291
|
+
"style",
|
292
|
+
"summary",
|
293
|
+
"tabindex",
|
294
|
+
"target",
|
295
|
+
"title",
|
296
|
+
"type",
|
297
|
+
"usemap",
|
298
|
+
"valign",
|
299
|
+
"value",
|
300
|
+
"vspace",
|
301
|
+
"width",
|
302
|
+
"xml:lang",
|
303
|
+
])
|
304
|
+
|
305
|
+
MATHML_ATTRIBUTES = Set.new([
|
306
|
+
"actiontype",
|
307
|
+
"align",
|
308
|
+
"close",
|
309
|
+
"columnalign",
|
310
|
+
"columnlines",
|
311
|
+
"columnspacing",
|
312
|
+
"columnspan",
|
313
|
+
"depth",
|
314
|
+
"display",
|
315
|
+
"displaystyle",
|
316
|
+
"encoding",
|
317
|
+
"equalcolumns",
|
318
|
+
"equalrows",
|
319
|
+
"fence",
|
320
|
+
"fontstyle",
|
321
|
+
"fontweight",
|
322
|
+
"frame",
|
323
|
+
"height",
|
324
|
+
"linethickness",
|
325
|
+
"lspace",
|
326
|
+
"mathbackground",
|
327
|
+
"mathcolor",
|
328
|
+
"mathvariant",
|
329
|
+
"maxsize",
|
330
|
+
"minsize",
|
331
|
+
"open",
|
332
|
+
"other",
|
333
|
+
"rowalign",
|
334
|
+
"rowlines",
|
335
|
+
"rowspacing",
|
336
|
+
"rowspan",
|
337
|
+
"rspace",
|
338
|
+
"scriptlevel",
|
339
|
+
"selection",
|
340
|
+
"separator",
|
341
|
+
"separators",
|
342
|
+
"stretchy",
|
343
|
+
"width",
|
344
|
+
"xlink:href",
|
345
|
+
"xlink:show",
|
346
|
+
"xlink:type",
|
347
|
+
"xmlns",
|
348
|
+
"xmlns:xlink",
|
349
|
+
])
|
350
|
+
|
351
|
+
SVG_ATTRIBUTES = Set.new([
|
352
|
+
"accent-height",
|
353
|
+
"accumulate",
|
354
|
+
"additive",
|
355
|
+
"alphabetic",
|
356
|
+
"arabic-form",
|
357
|
+
"ascent",
|
358
|
+
"attributeName",
|
359
|
+
"attributeType",
|
360
|
+
"baseProfile",
|
361
|
+
"bbox",
|
362
|
+
"begin",
|
363
|
+
"calcMode",
|
364
|
+
"cap-height",
|
365
|
+
"class",
|
366
|
+
"clip-path",
|
367
|
+
"clip-rule",
|
368
|
+
"color",
|
369
|
+
"color-interpolation-filters",
|
370
|
+
"color-rendering",
|
371
|
+
"content",
|
372
|
+
"cx",
|
373
|
+
"cy",
|
374
|
+
"d",
|
375
|
+
"descent",
|
376
|
+
"display",
|
377
|
+
"dur",
|
378
|
+
"dx",
|
379
|
+
"dy",
|
380
|
+
"end",
|
381
|
+
"fill",
|
382
|
+
"fill-opacity",
|
383
|
+
"fill-rule",
|
384
|
+
"filterRes",
|
385
|
+
"filterUnits",
|
386
|
+
"font-family",
|
387
|
+
"font-size",
|
388
|
+
"font-stretch",
|
389
|
+
"font-style",
|
390
|
+
"font-variant",
|
391
|
+
"font-weight",
|
392
|
+
"fx",
|
393
|
+
"fy",
|
394
|
+
"g1",
|
395
|
+
"g2",
|
396
|
+
"glyph-name",
|
397
|
+
"gradientUnits",
|
398
|
+
"hanging",
|
399
|
+
"height",
|
400
|
+
"horiz-adv-x",
|
401
|
+
"horiz-origin-x",
|
402
|
+
"id",
|
403
|
+
"ideographic",
|
404
|
+
"k",
|
405
|
+
"keyPoints",
|
406
|
+
"keySplines",
|
407
|
+
"keyTimes",
|
408
|
+
"lang",
|
409
|
+
"marker-end",
|
410
|
+
"marker-mid",
|
411
|
+
"marker-start",
|
412
|
+
"markerHeight",
|
413
|
+
"markerUnits",
|
414
|
+
"markerWidth",
|
415
|
+
"maskContentUnits",
|
416
|
+
"maskUnits",
|
417
|
+
"mathematical",
|
418
|
+
"max",
|
419
|
+
"method",
|
420
|
+
"min",
|
421
|
+
"name",
|
422
|
+
"offset",
|
423
|
+
"opacity",
|
424
|
+
"orient",
|
425
|
+
"origin",
|
426
|
+
"overline-position",
|
427
|
+
"overline-thickness",
|
428
|
+
"panose-1",
|
429
|
+
"path",
|
430
|
+
"pathLength",
|
431
|
+
"patternContentUnits",
|
432
|
+
"patternTransform",
|
433
|
+
"patternUnits",
|
434
|
+
"points",
|
435
|
+
"preserveAspectRatio",
|
436
|
+
"primitiveUnits",
|
437
|
+
"r",
|
438
|
+
"refX",
|
439
|
+
"refY",
|
440
|
+
"repeatCount",
|
441
|
+
"repeatDur",
|
442
|
+
"requiredExtensions",
|
443
|
+
"requiredFeatures",
|
444
|
+
"restart",
|
445
|
+
"rotate",
|
446
|
+
"rx",
|
447
|
+
"ry",
|
448
|
+
"slope",
|
449
|
+
"spacing",
|
450
|
+
"startOffset",
|
451
|
+
"stdDeviation",
|
452
|
+
"stemh",
|
453
|
+
"stemv",
|
454
|
+
"stop-color",
|
455
|
+
"stop-opacity",
|
456
|
+
"strikethrough-position",
|
457
|
+
"strikethrough-thickness",
|
458
|
+
"stroke",
|
459
|
+
"stroke-dasharray",
|
460
|
+
"stroke-dashoffset",
|
461
|
+
"stroke-linecap",
|
462
|
+
"stroke-linejoin",
|
463
|
+
"stroke-miterlimit",
|
464
|
+
"stroke-opacity",
|
465
|
+
"stroke-width",
|
466
|
+
"systemLanguage",
|
467
|
+
"target",
|
468
|
+
"text-anchor",
|
469
|
+
"transform",
|
470
|
+
"type",
|
471
|
+
"u1",
|
472
|
+
"u2",
|
473
|
+
"underline-position",
|
474
|
+
"underline-thickness",
|
475
|
+
"unicode",
|
476
|
+
"unicode-range",
|
477
|
+
"units-per-em",
|
478
|
+
"version",
|
479
|
+
"viewBox",
|
480
|
+
"visibility",
|
481
|
+
"width",
|
482
|
+
"widths",
|
483
|
+
"x",
|
484
|
+
"x-height",
|
485
|
+
"x1",
|
486
|
+
"x2",
|
487
|
+
"xlink:actuate",
|
488
|
+
"xlink:arcrole",
|
489
|
+
"xlink:href",
|
490
|
+
"xlink:role",
|
491
|
+
"xlink:show",
|
492
|
+
"xlink:title",
|
493
|
+
"xlink:type",
|
494
|
+
"xml:base",
|
495
|
+
"xml:lang",
|
496
|
+
"xml:space",
|
497
|
+
"xmlns",
|
498
|
+
"xmlns:xlink",
|
499
|
+
"y",
|
500
|
+
"y1",
|
501
|
+
"y2",
|
502
|
+
"zoomAndPan",
|
503
|
+
])
|
504
|
+
|
505
|
+
ATTR_VAL_IS_URI = Set.new([
|
506
|
+
"action",
|
507
|
+
"cite",
|
508
|
+
"href",
|
509
|
+
"longdesc",
|
510
|
+
"poster",
|
511
|
+
"preload",
|
512
|
+
"src",
|
513
|
+
"xlink:href",
|
514
|
+
"xml:base",
|
515
|
+
])
|
516
|
+
|
517
|
+
SVG_ATTR_VAL_ALLOWS_REF = Set.new([
|
518
|
+
"clip-path",
|
519
|
+
"color-profile",
|
520
|
+
"cursor",
|
521
|
+
"fill",
|
522
|
+
"filter",
|
523
|
+
"marker",
|
524
|
+
"marker-end",
|
525
|
+
"marker-mid",
|
526
|
+
"marker-start",
|
527
|
+
"mask",
|
528
|
+
"stroke",
|
529
|
+
])
|
530
|
+
|
531
|
+
SVG_ALLOW_LOCAL_HREF = Set.new([
|
532
|
+
"altGlyph",
|
533
|
+
"animate",
|
534
|
+
"animateColor",
|
535
|
+
"animateMotion",
|
536
|
+
"animateTransform",
|
537
|
+
"cursor",
|
538
|
+
"feImage",
|
539
|
+
"filter",
|
540
|
+
"linearGradient",
|
541
|
+
"pattern",
|
542
|
+
"radialGradient",
|
543
|
+
"set",
|
544
|
+
"textpath",
|
545
|
+
"tref",
|
546
|
+
"use",
|
547
|
+
])
|
548
|
+
|
549
|
+
ACCEPTABLE_CSS_PROPERTIES = Set.new([
|
550
|
+
"azimuth",
|
551
|
+
"background-color",
|
552
|
+
"border-bottom-color",
|
553
|
+
"border-collapse",
|
554
|
+
"border-color",
|
555
|
+
"border-left-color",
|
556
|
+
"border-right-color",
|
557
|
+
"border-top-color",
|
558
|
+
"clear",
|
559
|
+
"color",
|
560
|
+
"cursor",
|
561
|
+
"direction",
|
562
|
+
"display",
|
563
|
+
"elevation",
|
564
|
+
"float",
|
565
|
+
"font",
|
566
|
+
"font-family",
|
567
|
+
"font-size",
|
568
|
+
"font-style",
|
569
|
+
"font-variant",
|
570
|
+
"font-weight",
|
571
|
+
"height",
|
572
|
+
"letter-spacing",
|
573
|
+
"line-height",
|
574
|
+
"list-style",
|
575
|
+
"list-style-type",
|
576
|
+
"overflow",
|
577
|
+
"pause",
|
578
|
+
"pause-after",
|
579
|
+
"pause-before",
|
580
|
+
"pitch",
|
581
|
+
"pitch-range",
|
582
|
+
"richness",
|
583
|
+
"speak",
|
584
|
+
"speak-header",
|
585
|
+
"speak-numeral",
|
586
|
+
"speak-punctuation",
|
587
|
+
"speech-rate",
|
588
|
+
"stress",
|
589
|
+
"text-align",
|
590
|
+
"text-decoration",
|
591
|
+
"text-indent",
|
592
|
+
"unicode-bidi",
|
593
|
+
"vertical-align",
|
594
|
+
"voice-family",
|
595
|
+
"volume",
|
596
|
+
"white-space",
|
597
|
+
"width",
|
598
|
+
])
|
599
|
+
|
600
|
+
ACCEPTABLE_CSS_KEYWORDS = Set.new([
|
601
|
+
"!important",
|
602
|
+
"aqua",
|
603
|
+
"auto",
|
604
|
+
"black",
|
605
|
+
"block",
|
606
|
+
"blue",
|
607
|
+
"bold",
|
608
|
+
"both",
|
609
|
+
"bottom",
|
610
|
+
"brown",
|
611
|
+
"center",
|
612
|
+
"collapse",
|
613
|
+
"dashed",
|
614
|
+
"dotted",
|
615
|
+
"fuchsia",
|
616
|
+
"gray",
|
617
|
+
"green",
|
618
|
+
"italic",
|
619
|
+
"left",
|
620
|
+
"lime",
|
621
|
+
"maroon",
|
622
|
+
"medium",
|
623
|
+
"navy",
|
624
|
+
"none",
|
625
|
+
"normal",
|
626
|
+
"nowrap",
|
627
|
+
"olive",
|
628
|
+
"pointer",
|
629
|
+
"purple",
|
630
|
+
"red",
|
631
|
+
"right",
|
632
|
+
"silver",
|
633
|
+
"solid",
|
634
|
+
"teal",
|
635
|
+
"thin",
|
636
|
+
"thick",
|
637
|
+
"top",
|
638
|
+
"transparent",
|
639
|
+
"underline",
|
640
|
+
"white",
|
641
|
+
"yellow",
|
642
|
+
])
|
643
|
+
|
644
|
+
# see https://www.quackit.com/css/functions/
|
645
|
+
# omit `url` and `image` from that list
|
646
|
+
ACCEPTABLE_CSS_FUNCTIONS = Set.new([
|
647
|
+
"attr",
|
648
|
+
"blur",
|
649
|
+
"brightness",
|
650
|
+
"calc",
|
651
|
+
"circle",
|
652
|
+
"contrast",
|
653
|
+
"counter",
|
654
|
+
"counters",
|
655
|
+
"cubic-bezier",
|
656
|
+
"drop-shadow",
|
657
|
+
"ellipse",
|
658
|
+
"grayscale",
|
659
|
+
"hsl",
|
660
|
+
"hsla",
|
661
|
+
"hue-rotate",
|
662
|
+
"hwb",
|
663
|
+
"inset",
|
664
|
+
"invert",
|
665
|
+
"linear-gradient",
|
666
|
+
"matrix",
|
667
|
+
"matrix3d",
|
668
|
+
"opacity",
|
669
|
+
"perspective",
|
670
|
+
"polygon",
|
671
|
+
"radial-gradient",
|
672
|
+
"repeating-linear-gradient",
|
673
|
+
"repeating-radial-gradient",
|
674
|
+
"rgb",
|
675
|
+
"rgba",
|
676
|
+
"rotate",
|
677
|
+
"rotate3d",
|
678
|
+
"rotateX",
|
679
|
+
"rotateY",
|
680
|
+
"rotateZ",
|
681
|
+
"saturate",
|
682
|
+
"sepia",
|
683
|
+
"scale",
|
684
|
+
"scale3d",
|
685
|
+
"scaleX",
|
686
|
+
"scaleY",
|
687
|
+
"scaleZ",
|
688
|
+
"skew",
|
689
|
+
"skewX",
|
690
|
+
"skewY",
|
691
|
+
"symbols",
|
692
|
+
"translate",
|
693
|
+
"translate3d",
|
694
|
+
"translateX",
|
695
|
+
"translateY",
|
696
|
+
"translateZ",
|
697
|
+
])
|
698
|
+
|
699
|
+
SHORTHAND_CSS_PROPERTIES = Set.new([
|
700
|
+
"background",
|
701
|
+
"border",
|
702
|
+
"margin",
|
703
|
+
"padding",
|
704
|
+
])
|
705
|
+
|
706
|
+
ACCEPTABLE_SVG_PROPERTIES = Set.new([
|
707
|
+
"fill",
|
708
|
+
"fill-opacity",
|
709
|
+
"fill-rule",
|
710
|
+
"stroke",
|
711
|
+
"stroke-width",
|
712
|
+
"stroke-linecap",
|
713
|
+
"stroke-linejoin",
|
714
|
+
"stroke-opacity",
|
715
|
+
])
|
716
|
+
|
717
|
+
PROTOCOL_SEPARATOR = /:|(�*58)|(p)|(�*3a)|(%|%)3A/i
|
718
|
+
|
719
|
+
ACCEPTABLE_PROTOCOLS = Set.new([
|
720
|
+
"afs",
|
721
|
+
"aim",
|
722
|
+
"callto",
|
723
|
+
"data",
|
724
|
+
"ed2k",
|
725
|
+
"feed",
|
726
|
+
"ftp",
|
727
|
+
"gopher",
|
728
|
+
"http",
|
729
|
+
"https",
|
730
|
+
"irc",
|
731
|
+
"line",
|
732
|
+
"mailto",
|
733
|
+
"news",
|
734
|
+
"nntp",
|
735
|
+
"rsync",
|
736
|
+
"rtsp",
|
737
|
+
"sftp",
|
738
|
+
"ssh",
|
739
|
+
"tag",
|
740
|
+
"tel",
|
741
|
+
"telnet",
|
742
|
+
"urn",
|
743
|
+
"webcal",
|
744
|
+
"xmpp",
|
745
|
+
])
|
746
|
+
|
747
|
+
ACCEPTABLE_URI_DATA_MEDIATYPES = Set.new([
|
748
|
+
"image/gif",
|
749
|
+
"image/jpeg",
|
750
|
+
"image/png",
|
751
|
+
"image/svg+xml",
|
752
|
+
"text/css",
|
753
|
+
"text/plain",
|
754
|
+
])
|
755
|
+
|
756
|
+
# subclasses may define their own versions of these constants
|
757
|
+
ALLOWED_ELEMENTS = ACCEPTABLE_ELEMENTS + MATHML_ELEMENTS + SVG_ELEMENTS
|
758
|
+
ALLOWED_ATTRIBUTES = ACCEPTABLE_ATTRIBUTES + MATHML_ATTRIBUTES + SVG_ATTRIBUTES
|
759
|
+
ALLOWED_CSS_PROPERTIES = ACCEPTABLE_CSS_PROPERTIES
|
760
|
+
ALLOWED_CSS_KEYWORDS = ACCEPTABLE_CSS_KEYWORDS
|
761
|
+
ALLOWED_CSS_FUNCTIONS = ACCEPTABLE_CSS_FUNCTIONS
|
762
|
+
ALLOWED_SVG_PROPERTIES = ACCEPTABLE_SVG_PROPERTIES
|
763
|
+
ALLOWED_PROTOCOLS = ACCEPTABLE_PROTOCOLS
|
764
|
+
ALLOWED_URI_DATA_MEDIATYPES = ACCEPTABLE_URI_DATA_MEDIATYPES
|
765
|
+
|
766
|
+
VOID_ELEMENTS = Set.new([
|
767
|
+
"area",
|
768
|
+
"base",
|
769
|
+
"br",
|
770
|
+
"col",
|
771
|
+
"embed",
|
772
|
+
"hr",
|
773
|
+
"img",
|
774
|
+
"input",
|
775
|
+
"link",
|
776
|
+
"meta",
|
777
|
+
"param",
|
778
|
+
])
|
779
|
+
|
780
|
+
# additional tags we should consider safe since we have libxml2 fixing up our documents.
|
781
|
+
TAGS_SAFE_WITH_LIBXML2 = Set.new([
|
782
|
+
"body",
|
783
|
+
"head",
|
784
|
+
"html",
|
785
|
+
])
|
786
|
+
ALLOWED_ELEMENTS_WITH_LIBXML2 = ALLOWED_ELEMENTS + TAGS_SAFE_WITH_LIBXML2
|
787
|
+
end
|
788
|
+
|
789
|
+
WhiteList = SafeList
|
790
|
+
if Object.respond_to?(:deprecate_constant)
|
791
|
+
deprecate_constant :WhiteList
|
792
|
+
end
|
793
|
+
|
794
|
+
::Loofah::MetaHelpers.add_downcased_set_members_to_all_set_constants ::Loofah::HTML5::SafeList
|
795
|
+
end
|
796
|
+
end
|