loofah 2.1.1 → 2.3.0
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 +5 -5
- data/CHANGELOG.md +110 -31
- data/Gemfile +3 -3
- data/MIT-LICENSE.txt +1 -1
- data/Manifest.txt +6 -2
- data/README.md +369 -0
- data/Rakefile +23 -21
- data/SECURITY.md +18 -0
- data/lib/loofah.rb +15 -14
- data/lib/loofah/elements.rb +81 -6
- data/lib/loofah/helpers.rb +13 -3
- data/lib/loofah/html5/libxml2_workarounds.rb +26 -0
- data/lib/loofah/html5/safelist.rb +800 -0
- data/lib/loofah/html5/scrub.rb +43 -16
- data/lib/loofah/scrubbers.rb +7 -2
- data/test/assets/msword.html +63 -0
- data/test/html5/test_sanitizer.rb +67 -16
- data/test/html5/test_scrub.rb +10 -0
- data/test/integration/test_ad_hoc.rb +161 -133
- data/test/integration/test_html.rb +12 -2
- data/test/unit/test_helpers.rb +4 -4
- metadata +50 -41
- data/README.rdoc +0 -314
- data/lib/loofah/html5/whitelist.rb +0 -183
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
|
@@ -12,23 +11,23 @@ Hoe.spec "loofah" do
|
|
12
11
|
developer "Mike Dalessio", "mike.dalessio@gmail.com"
|
13
12
|
developer "Bryan Helmkamp", "bryan@brynary.com"
|
14
13
|
|
15
|
-
self.extra_rdoc_files = FileList["*.
|
16
|
-
self.history_file
|
17
|
-
self.readme_file
|
18
|
-
self.license
|
14
|
+
self.extra_rdoc_files = FileList["*.md"]
|
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/SECURITY.md
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# Security and Vulnerability Reporting
|
2
|
+
|
3
|
+
The Loofah core contributors take security very seriously and investigate all reported vulnerabilities.
|
4
|
+
|
5
|
+
If you would like to report a vulnerablity or have a security concern regarding Loofah, please [report it via HackerOne](https://hackerone.com/loofah/reports/new).
|
6
|
+
|
7
|
+
Your report will be acknowledged within 24 hours, and you'll receive a more detailed response within 72 hours indicating next steps in handling your report.
|
8
|
+
|
9
|
+
If you have not received a reply to your submission within 48 hours, there are a few steps you can take:
|
10
|
+
|
11
|
+
* Contact the current security coordinator (Mike Dalessio <mike.dalessio@gmail.com>)
|
12
|
+
* Email the Loofah user group at loofah-talk@googlegroups.com (archive at https://groups.google.com/forum/#!forum/loofah-talk)
|
13
|
+
|
14
|
+
Please note, the user group list is a public area. When escalating in that venue, please do not discuss your issue. Simply say that you're trying to get a hold of someone from the core team.
|
15
|
+
|
16
|
+
The information you share with the Loofah core contributors as part of this process will be kept confidential within the team, unless or until we need to share information upstream with our dependent libraries' core teams, at which point we will notify you.
|
17
|
+
|
18
|
+
If a vulnerability is first reported by you, we will credit you with the discovery in the public disclosure.
|
data/lib/loofah.rb
CHANGED
@@ -1,21 +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
|
8
|
+
require "loofah/html5/safelist"
|
9
|
+
require "loofah/html5/libxml2_workarounds"
|
10
|
+
require "loofah/html5/scrub"
|
10
11
|
|
11
|
-
require
|
12
|
-
require
|
12
|
+
require "loofah/scrubber"
|
13
|
+
require "loofah/scrubbers"
|
13
14
|
|
14
|
-
require
|
15
|
-
require
|
16
|
-
require
|
17
|
-
require
|
18
|
-
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"
|
19
20
|
|
20
21
|
# == Strings and IO Objects as Input
|
21
22
|
#
|
@@ -27,7 +28,7 @@ require 'loofah/html/document_fragment'
|
|
27
28
|
#
|
28
29
|
module Loofah
|
29
30
|
# The version of Loofah you are using
|
30
|
-
VERSION =
|
31
|
+
VERSION = "2.3.0"
|
31
32
|
|
32
33
|
class << self
|
33
34
|
# Shortcut for Loofah::HTML::Document.parse
|
@@ -76,7 +77,7 @@ module Loofah
|
|
76
77
|
|
77
78
|
# A helper to remove extraneous whitespace from text-ified HTML
|
78
79
|
def remove_extraneous_whitespace(string)
|
79
|
-
string.gsub(/\n\s*\n\s*\n/,"\n\n")
|
80
|
+
string.gsub(/\n\s*\n\s*\n/, "\n\n")
|
80
81
|
end
|
81
82
|
end
|
82
83
|
end
|
data/lib/loofah/elements.rb
CHANGED
@@ -2,13 +2,88 @@ require 'set'
|
|
2
2
|
|
3
3
|
module Loofah
|
4
4
|
module Elements
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
STRICT_BLOCK_LEVEL_HTML4 = Set.new %w[
|
6
|
+
address
|
7
|
+
blockquote
|
8
|
+
center
|
9
|
+
dir
|
10
|
+
div
|
11
|
+
dl
|
12
|
+
fieldset
|
13
|
+
form
|
14
|
+
h1
|
15
|
+
h2
|
16
|
+
h3
|
17
|
+
h4
|
18
|
+
h5
|
19
|
+
h6
|
20
|
+
hr
|
21
|
+
isindex
|
22
|
+
menu
|
23
|
+
noframes
|
24
|
+
noscript
|
25
|
+
ol
|
26
|
+
p
|
27
|
+
pre
|
28
|
+
table
|
29
|
+
ul
|
30
|
+
]
|
9
31
|
|
10
|
-
#
|
11
|
-
|
32
|
+
# https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements
|
33
|
+
STRICT_BLOCK_LEVEL_HTML5 = Set.new %w[
|
34
|
+
address
|
35
|
+
article
|
36
|
+
aside
|
37
|
+
blockquote
|
38
|
+
canvas
|
39
|
+
dd
|
40
|
+
div
|
41
|
+
dl
|
42
|
+
dt
|
43
|
+
fieldset
|
44
|
+
figcaption
|
45
|
+
figure
|
46
|
+
footer
|
47
|
+
form
|
48
|
+
h1
|
49
|
+
h2
|
50
|
+
h3
|
51
|
+
h4
|
52
|
+
h5
|
53
|
+
h6
|
54
|
+
header
|
55
|
+
hgroup
|
56
|
+
hr
|
57
|
+
li
|
58
|
+
main
|
59
|
+
nav
|
60
|
+
noscript
|
61
|
+
ol
|
62
|
+
output
|
63
|
+
p
|
64
|
+
pre
|
65
|
+
section
|
66
|
+
table
|
67
|
+
tfoot
|
68
|
+
ul
|
69
|
+
video
|
70
|
+
]
|
71
|
+
|
72
|
+
STRICT_BLOCK_LEVEL = STRICT_BLOCK_LEVEL_HTML4 + STRICT_BLOCK_LEVEL_HTML5
|
73
|
+
|
74
|
+
# The following elements may also be considered block-level
|
75
|
+
# elements since they may contain block-level elements
|
76
|
+
LOOSE_BLOCK_LEVEL = Set.new %w[dd
|
77
|
+
dt
|
78
|
+
frameset
|
79
|
+
li
|
80
|
+
tbody
|
81
|
+
td
|
82
|
+
tfoot
|
83
|
+
th
|
84
|
+
thead
|
85
|
+
tr
|
86
|
+
]
|
12
87
|
|
13
88
|
BLOCK_LEVEL = STRICT_BLOCK_LEVEL + LOOSE_BLOCK_LEVEL
|
14
89
|
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,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
module Loofah
|
5
|
+
#
|
6
|
+
# constants related to working around unhelpful libxml2 behavior
|
7
|
+
#
|
8
|
+
# ಠ_ಠ
|
9
|
+
#
|
10
|
+
module LibxmlWorkarounds
|
11
|
+
#
|
12
|
+
# these attributes and qualifying parent tags are determined by the code at:
|
13
|
+
#
|
14
|
+
# https://git.gnome.org/browse/libxml2/tree/HTMLtree.c?h=v2.9.2#n714
|
15
|
+
#
|
16
|
+
# see comments about CVE-2018-8048 within the tests for more information
|
17
|
+
#
|
18
|
+
BROKEN_ESCAPING_ATTRIBUTES = Set.new %w[
|
19
|
+
href
|
20
|
+
action
|
21
|
+
src
|
22
|
+
name
|
23
|
+
]
|
24
|
+
BROKEN_ESCAPING_ATTRIBUTES_QUALIFYING_TAG = {"name" => "a"}
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,800 @@
|
|
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
|
+
|
49
|
+
ACCEPTABLE_ELEMENTS = Set.new([
|
50
|
+
"a",
|
51
|
+
"abbr",
|
52
|
+
"acronym",
|
53
|
+
"address",
|
54
|
+
"area",
|
55
|
+
"article",
|
56
|
+
"aside",
|
57
|
+
"audio",
|
58
|
+
"b",
|
59
|
+
"bdi",
|
60
|
+
"bdo",
|
61
|
+
"big",
|
62
|
+
"blockquote",
|
63
|
+
"br",
|
64
|
+
"button",
|
65
|
+
"canvas",
|
66
|
+
"caption",
|
67
|
+
"center",
|
68
|
+
"cite",
|
69
|
+
"code",
|
70
|
+
"col",
|
71
|
+
"colgroup",
|
72
|
+
"command",
|
73
|
+
"datalist",
|
74
|
+
"dd",
|
75
|
+
"del",
|
76
|
+
"details",
|
77
|
+
"dfn",
|
78
|
+
"dir",
|
79
|
+
"div",
|
80
|
+
"dl",
|
81
|
+
"dt",
|
82
|
+
"em",
|
83
|
+
"fieldset",
|
84
|
+
"figcaption",
|
85
|
+
"figure",
|
86
|
+
"font",
|
87
|
+
"footer",
|
88
|
+
"form",
|
89
|
+
"h1",
|
90
|
+
"h2",
|
91
|
+
"h3",
|
92
|
+
"h4",
|
93
|
+
"h5",
|
94
|
+
"h6",
|
95
|
+
"header",
|
96
|
+
"hr",
|
97
|
+
"i",
|
98
|
+
"img",
|
99
|
+
"input",
|
100
|
+
"ins",
|
101
|
+
"kbd",
|
102
|
+
"label",
|
103
|
+
"legend",
|
104
|
+
"li",
|
105
|
+
"main",
|
106
|
+
"map",
|
107
|
+
"mark",
|
108
|
+
"menu",
|
109
|
+
"meter",
|
110
|
+
"nav",
|
111
|
+
"ol",
|
112
|
+
"optgroup",
|
113
|
+
"option",
|
114
|
+
"output",
|
115
|
+
"p",
|
116
|
+
"pre",
|
117
|
+
"q",
|
118
|
+
"s",
|
119
|
+
"samp",
|
120
|
+
"section",
|
121
|
+
"select",
|
122
|
+
"small",
|
123
|
+
"span",
|
124
|
+
"strike",
|
125
|
+
"strong",
|
126
|
+
"sub",
|
127
|
+
"summary",
|
128
|
+
"sup",
|
129
|
+
"table",
|
130
|
+
"tbody",
|
131
|
+
"td",
|
132
|
+
"textarea",
|
133
|
+
"tfoot",
|
134
|
+
"th",
|
135
|
+
"thead",
|
136
|
+
"time",
|
137
|
+
"tr",
|
138
|
+
"tt",
|
139
|
+
"u",
|
140
|
+
"ul",
|
141
|
+
"var",
|
142
|
+
"video",
|
143
|
+
])
|
144
|
+
|
145
|
+
MATHML_ELEMENTS = Set.new([
|
146
|
+
"annotation",
|
147
|
+
"annotation-xml",
|
148
|
+
"maction",
|
149
|
+
"math",
|
150
|
+
"merror",
|
151
|
+
"mfenced",
|
152
|
+
"mfrac",
|
153
|
+
"mi",
|
154
|
+
"mmultiscripts",
|
155
|
+
"mn",
|
156
|
+
"mo",
|
157
|
+
"mover",
|
158
|
+
"mpadded",
|
159
|
+
"mphantom",
|
160
|
+
"mprescripts",
|
161
|
+
"mroot",
|
162
|
+
"mrow",
|
163
|
+
"mspace",
|
164
|
+
"msqrt",
|
165
|
+
"mstyle",
|
166
|
+
"msub",
|
167
|
+
"msubsup",
|
168
|
+
"msup",
|
169
|
+
"mtable",
|
170
|
+
"mtd",
|
171
|
+
"mtext",
|
172
|
+
"mtr",
|
173
|
+
"munder",
|
174
|
+
"munderover",
|
175
|
+
"none",
|
176
|
+
"semantics",
|
177
|
+
])
|
178
|
+
|
179
|
+
SVG_ELEMENTS = Set.new([
|
180
|
+
"a",
|
181
|
+
"animate",
|
182
|
+
"animateColor",
|
183
|
+
"animateMotion",
|
184
|
+
"animateTransform",
|
185
|
+
"circle",
|
186
|
+
"clipPath",
|
187
|
+
"defs",
|
188
|
+
"desc",
|
189
|
+
"ellipse",
|
190
|
+
"feGaussianBlur",
|
191
|
+
"filter",
|
192
|
+
"font-face",
|
193
|
+
"font-face-name",
|
194
|
+
"font-face-src",
|
195
|
+
"foreignObject",
|
196
|
+
"g",
|
197
|
+
"glyph",
|
198
|
+
"hkern",
|
199
|
+
"line",
|
200
|
+
"linearGradient",
|
201
|
+
"marker",
|
202
|
+
"mask",
|
203
|
+
"metadata",
|
204
|
+
"missing-glyph",
|
205
|
+
"mpath",
|
206
|
+
"path",
|
207
|
+
"polygon",
|
208
|
+
"polyline",
|
209
|
+
"radialGradient",
|
210
|
+
"rect",
|
211
|
+
"set",
|
212
|
+
"stop",
|
213
|
+
"svg",
|
214
|
+
"switch",
|
215
|
+
"symbol",
|
216
|
+
"text",
|
217
|
+
"textPath",
|
218
|
+
"title",
|
219
|
+
"tspan",
|
220
|
+
"use",
|
221
|
+
])
|
222
|
+
|
223
|
+
ACCEPTABLE_ATTRIBUTES = Set.new([
|
224
|
+
"abbr",
|
225
|
+
"accept",
|
226
|
+
"accept-charset",
|
227
|
+
"accesskey",
|
228
|
+
"action",
|
229
|
+
"align",
|
230
|
+
"alt",
|
231
|
+
"axis",
|
232
|
+
"border",
|
233
|
+
"cellpadding",
|
234
|
+
"cellspacing",
|
235
|
+
"char",
|
236
|
+
"charoff",
|
237
|
+
"charset",
|
238
|
+
"checked",
|
239
|
+
"cite",
|
240
|
+
"class",
|
241
|
+
"clear",
|
242
|
+
"color",
|
243
|
+
"cols",
|
244
|
+
"colspan",
|
245
|
+
"compact",
|
246
|
+
"contenteditable",
|
247
|
+
"coords",
|
248
|
+
"datetime",
|
249
|
+
"dir",
|
250
|
+
"disabled",
|
251
|
+
"enctype",
|
252
|
+
"for",
|
253
|
+
"frame",
|
254
|
+
"headers",
|
255
|
+
"height",
|
256
|
+
"href",
|
257
|
+
"hreflang",
|
258
|
+
"hspace",
|
259
|
+
"id",
|
260
|
+
"ismap",
|
261
|
+
"label",
|
262
|
+
"lang",
|
263
|
+
"longdesc",
|
264
|
+
"loop",
|
265
|
+
"loopcount",
|
266
|
+
"loopend",
|
267
|
+
"loopstart",
|
268
|
+
"maxlength",
|
269
|
+
"media",
|
270
|
+
"method",
|
271
|
+
"multiple",
|
272
|
+
"name",
|
273
|
+
"nohref",
|
274
|
+
"noshade",
|
275
|
+
"nowrap",
|
276
|
+
"poster",
|
277
|
+
"preload",
|
278
|
+
"prompt",
|
279
|
+
"readonly",
|
280
|
+
"rel",
|
281
|
+
"rev",
|
282
|
+
"rows",
|
283
|
+
"rowspan",
|
284
|
+
"rules",
|
285
|
+
"scope",
|
286
|
+
"selected",
|
287
|
+
"shape",
|
288
|
+
"size",
|
289
|
+
"span",
|
290
|
+
"src",
|
291
|
+
"start",
|
292
|
+
"style",
|
293
|
+
"summary",
|
294
|
+
"tabindex",
|
295
|
+
"target",
|
296
|
+
"title",
|
297
|
+
"type",
|
298
|
+
"usemap",
|
299
|
+
"valign",
|
300
|
+
"value",
|
301
|
+
"vspace",
|
302
|
+
"width",
|
303
|
+
"xml:lang",
|
304
|
+
])
|
305
|
+
|
306
|
+
MATHML_ATTRIBUTES = Set.new([
|
307
|
+
"actiontype",
|
308
|
+
"align",
|
309
|
+
"close",
|
310
|
+
"columnalign",
|
311
|
+
"columnlines",
|
312
|
+
"columnspacing",
|
313
|
+
"columnspan",
|
314
|
+
"depth",
|
315
|
+
"display",
|
316
|
+
"displaystyle",
|
317
|
+
"encoding",
|
318
|
+
"equalcolumns",
|
319
|
+
"equalrows",
|
320
|
+
"fence",
|
321
|
+
"fontstyle",
|
322
|
+
"fontweight",
|
323
|
+
"frame",
|
324
|
+
"height",
|
325
|
+
"linethickness",
|
326
|
+
"lspace",
|
327
|
+
"mathbackground",
|
328
|
+
"mathcolor",
|
329
|
+
"mathvariant",
|
330
|
+
"maxsize",
|
331
|
+
"minsize",
|
332
|
+
"open",
|
333
|
+
"other",
|
334
|
+
"rowalign",
|
335
|
+
"rowlines",
|
336
|
+
"rowspacing",
|
337
|
+
"rowspan",
|
338
|
+
"rspace",
|
339
|
+
"scriptlevel",
|
340
|
+
"selection",
|
341
|
+
"separator",
|
342
|
+
"separators",
|
343
|
+
"stretchy",
|
344
|
+
"width",
|
345
|
+
"xlink:href",
|
346
|
+
"xlink:show",
|
347
|
+
"xlink:type",
|
348
|
+
"xmlns",
|
349
|
+
"xmlns:xlink",
|
350
|
+
])
|
351
|
+
|
352
|
+
SVG_ATTRIBUTES = Set.new([
|
353
|
+
"accent-height",
|
354
|
+
"accumulate",
|
355
|
+
"additive",
|
356
|
+
"alphabetic",
|
357
|
+
"arabic-form",
|
358
|
+
"ascent",
|
359
|
+
"attributeName",
|
360
|
+
"attributeType",
|
361
|
+
"baseProfile",
|
362
|
+
"bbox",
|
363
|
+
"begin",
|
364
|
+
"by",
|
365
|
+
"calcMode",
|
366
|
+
"cap-height",
|
367
|
+
"class",
|
368
|
+
"clip-path",
|
369
|
+
"clip-rule",
|
370
|
+
"color",
|
371
|
+
"color-interpolation-filters",
|
372
|
+
"color-rendering",
|
373
|
+
"content",
|
374
|
+
"cx",
|
375
|
+
"cy",
|
376
|
+
"d",
|
377
|
+
"descent",
|
378
|
+
"display",
|
379
|
+
"dur",
|
380
|
+
"dx",
|
381
|
+
"dy",
|
382
|
+
"end",
|
383
|
+
"fill",
|
384
|
+
"fill-opacity",
|
385
|
+
"fill-rule",
|
386
|
+
"filterRes",
|
387
|
+
"filterUnits",
|
388
|
+
"font-family",
|
389
|
+
"font-size",
|
390
|
+
"font-stretch",
|
391
|
+
"font-style",
|
392
|
+
"font-variant",
|
393
|
+
"font-weight",
|
394
|
+
"fx",
|
395
|
+
"fy",
|
396
|
+
"g1",
|
397
|
+
"g2",
|
398
|
+
"glyph-name",
|
399
|
+
"gradientUnits",
|
400
|
+
"hanging",
|
401
|
+
"height",
|
402
|
+
"horiz-adv-x",
|
403
|
+
"horiz-origin-x",
|
404
|
+
"id",
|
405
|
+
"ideographic",
|
406
|
+
"k",
|
407
|
+
"keyPoints",
|
408
|
+
"keySplines",
|
409
|
+
"keyTimes",
|
410
|
+
"lang",
|
411
|
+
"marker-end",
|
412
|
+
"marker-mid",
|
413
|
+
"marker-start",
|
414
|
+
"markerHeight",
|
415
|
+
"markerUnits",
|
416
|
+
"markerWidth",
|
417
|
+
"maskContentUnits",
|
418
|
+
"maskUnits",
|
419
|
+
"mathematical",
|
420
|
+
"max",
|
421
|
+
"method",
|
422
|
+
"min",
|
423
|
+
"name",
|
424
|
+
"offset",
|
425
|
+
"opacity",
|
426
|
+
"orient",
|
427
|
+
"origin",
|
428
|
+
"overline-position",
|
429
|
+
"overline-thickness",
|
430
|
+
"panose-1",
|
431
|
+
"path",
|
432
|
+
"pathLength",
|
433
|
+
"patternContentUnits",
|
434
|
+
"patternTransform",
|
435
|
+
"patternUnits",
|
436
|
+
"points",
|
437
|
+
"preserveAspectRatio",
|
438
|
+
"primitiveUnits",
|
439
|
+
"r",
|
440
|
+
"refX",
|
441
|
+
"refY",
|
442
|
+
"repeatCount",
|
443
|
+
"repeatDur",
|
444
|
+
"requiredExtensions",
|
445
|
+
"requiredFeatures",
|
446
|
+
"restart",
|
447
|
+
"rotate",
|
448
|
+
"rx",
|
449
|
+
"ry",
|
450
|
+
"slope",
|
451
|
+
"spacing",
|
452
|
+
"startOffset",
|
453
|
+
"stdDeviation",
|
454
|
+
"stemh",
|
455
|
+
"stemv",
|
456
|
+
"stop-color",
|
457
|
+
"stop-opacity",
|
458
|
+
"strikethrough-position",
|
459
|
+
"strikethrough-thickness",
|
460
|
+
"stroke",
|
461
|
+
"stroke-dasharray",
|
462
|
+
"stroke-dashoffset",
|
463
|
+
"stroke-linecap",
|
464
|
+
"stroke-linejoin",
|
465
|
+
"stroke-miterlimit",
|
466
|
+
"stroke-opacity",
|
467
|
+
"stroke-width",
|
468
|
+
"systemLanguage",
|
469
|
+
"target",
|
470
|
+
"text-anchor",
|
471
|
+
"to",
|
472
|
+
"transform",
|
473
|
+
"type",
|
474
|
+
"u1",
|
475
|
+
"u2",
|
476
|
+
"underline-position",
|
477
|
+
"underline-thickness",
|
478
|
+
"unicode",
|
479
|
+
"unicode-range",
|
480
|
+
"units-per-em",
|
481
|
+
"values",
|
482
|
+
"version",
|
483
|
+
"viewBox",
|
484
|
+
"visibility",
|
485
|
+
"width",
|
486
|
+
"widths",
|
487
|
+
"x",
|
488
|
+
"x-height",
|
489
|
+
"x1",
|
490
|
+
"x2",
|
491
|
+
"xlink:actuate",
|
492
|
+
"xlink:arcrole",
|
493
|
+
"xlink:href",
|
494
|
+
"xlink:role",
|
495
|
+
"xlink:show",
|
496
|
+
"xlink:title",
|
497
|
+
"xlink:type",
|
498
|
+
"xml:base",
|
499
|
+
"xml:lang",
|
500
|
+
"xml:space",
|
501
|
+
"xmlns",
|
502
|
+
"xmlns:xlink",
|
503
|
+
"y",
|
504
|
+
"y1",
|
505
|
+
"y2",
|
506
|
+
"zoomAndPan",
|
507
|
+
])
|
508
|
+
|
509
|
+
ATTR_VAL_IS_URI = Set.new([
|
510
|
+
"action",
|
511
|
+
"cite",
|
512
|
+
"href",
|
513
|
+
"longdesc",
|
514
|
+
"poster",
|
515
|
+
"preload",
|
516
|
+
"src",
|
517
|
+
"xlink:href",
|
518
|
+
"xml:base",
|
519
|
+
])
|
520
|
+
|
521
|
+
SVG_ATTR_VAL_ALLOWS_REF = Set.new([
|
522
|
+
"clip-path",
|
523
|
+
"color-profile",
|
524
|
+
"cursor",
|
525
|
+
"fill",
|
526
|
+
"filter",
|
527
|
+
"marker",
|
528
|
+
"marker-end",
|
529
|
+
"marker-mid",
|
530
|
+
"marker-start",
|
531
|
+
"mask",
|
532
|
+
"stroke",
|
533
|
+
])
|
534
|
+
|
535
|
+
SVG_ALLOW_LOCAL_HREF = Set.new([
|
536
|
+
"altGlyph",
|
537
|
+
"animate",
|
538
|
+
"animateColor",
|
539
|
+
"animateMotion",
|
540
|
+
"animateTransform",
|
541
|
+
"cursor",
|
542
|
+
"feImage",
|
543
|
+
"filter",
|
544
|
+
"linearGradient",
|
545
|
+
"pattern",
|
546
|
+
"radialGradient",
|
547
|
+
"set",
|
548
|
+
"textpath",
|
549
|
+
"tref",
|
550
|
+
"use",
|
551
|
+
])
|
552
|
+
|
553
|
+
ACCEPTABLE_CSS_PROPERTIES = Set.new([
|
554
|
+
"azimuth",
|
555
|
+
"background-color",
|
556
|
+
"border-bottom-color",
|
557
|
+
"border-collapse",
|
558
|
+
"border-color",
|
559
|
+
"border-left-color",
|
560
|
+
"border-right-color",
|
561
|
+
"border-top-color",
|
562
|
+
"clear",
|
563
|
+
"color",
|
564
|
+
"cursor",
|
565
|
+
"direction",
|
566
|
+
"display",
|
567
|
+
"elevation",
|
568
|
+
"float",
|
569
|
+
"font",
|
570
|
+
"font-family",
|
571
|
+
"font-size",
|
572
|
+
"font-style",
|
573
|
+
"font-variant",
|
574
|
+
"font-weight",
|
575
|
+
"height",
|
576
|
+
"letter-spacing",
|
577
|
+
"line-height",
|
578
|
+
"list-style",
|
579
|
+
"list-style-type",
|
580
|
+
"overflow",
|
581
|
+
"pause",
|
582
|
+
"pause-after",
|
583
|
+
"pause-before",
|
584
|
+
"pitch",
|
585
|
+
"pitch-range",
|
586
|
+
"richness",
|
587
|
+
"speak",
|
588
|
+
"speak-header",
|
589
|
+
"speak-numeral",
|
590
|
+
"speak-punctuation",
|
591
|
+
"speech-rate",
|
592
|
+
"stress",
|
593
|
+
"text-align",
|
594
|
+
"text-decoration",
|
595
|
+
"text-indent",
|
596
|
+
"unicode-bidi",
|
597
|
+
"vertical-align",
|
598
|
+
"voice-family",
|
599
|
+
"volume",
|
600
|
+
"white-space",
|
601
|
+
"width",
|
602
|
+
])
|
603
|
+
|
604
|
+
ACCEPTABLE_CSS_KEYWORDS = Set.new([
|
605
|
+
"!important",
|
606
|
+
"aqua",
|
607
|
+
"auto",
|
608
|
+
"black",
|
609
|
+
"block",
|
610
|
+
"blue",
|
611
|
+
"bold",
|
612
|
+
"both",
|
613
|
+
"bottom",
|
614
|
+
"brown",
|
615
|
+
"center",
|
616
|
+
"collapse",
|
617
|
+
"dashed",
|
618
|
+
"dotted",
|
619
|
+
"fuchsia",
|
620
|
+
"gray",
|
621
|
+
"green",
|
622
|
+
"italic",
|
623
|
+
"left",
|
624
|
+
"lime",
|
625
|
+
"maroon",
|
626
|
+
"medium",
|
627
|
+
"navy",
|
628
|
+
"none",
|
629
|
+
"normal",
|
630
|
+
"nowrap",
|
631
|
+
"olive",
|
632
|
+
"pointer",
|
633
|
+
"purple",
|
634
|
+
"red",
|
635
|
+
"right",
|
636
|
+
"silver",
|
637
|
+
"solid",
|
638
|
+
"teal",
|
639
|
+
"thin",
|
640
|
+
"thick",
|
641
|
+
"top",
|
642
|
+
"transparent",
|
643
|
+
"underline",
|
644
|
+
"white",
|
645
|
+
"yellow",
|
646
|
+
])
|
647
|
+
|
648
|
+
# see https://www.quackit.com/css/functions/
|
649
|
+
# omit `url` and `image` from that list
|
650
|
+
ACCEPTABLE_CSS_FUNCTIONS = Set.new([
|
651
|
+
"attr",
|
652
|
+
"blur",
|
653
|
+
"brightness",
|
654
|
+
"calc",
|
655
|
+
"circle",
|
656
|
+
"contrast",
|
657
|
+
"counter",
|
658
|
+
"counters",
|
659
|
+
"cubic-bezier",
|
660
|
+
"drop-shadow",
|
661
|
+
"ellipse",
|
662
|
+
"grayscale",
|
663
|
+
"hsl",
|
664
|
+
"hsla",
|
665
|
+
"hue-rotate",
|
666
|
+
"hwb",
|
667
|
+
"inset",
|
668
|
+
"invert",
|
669
|
+
"linear-gradient",
|
670
|
+
"matrix",
|
671
|
+
"matrix3d",
|
672
|
+
"opacity",
|
673
|
+
"perspective",
|
674
|
+
"polygon",
|
675
|
+
"radial-gradient",
|
676
|
+
"repeating-linear-gradient",
|
677
|
+
"repeating-radial-gradient",
|
678
|
+
"rgb",
|
679
|
+
"rgba",
|
680
|
+
"rotate",
|
681
|
+
"rotate3d",
|
682
|
+
"rotateX",
|
683
|
+
"rotateY",
|
684
|
+
"rotateZ",
|
685
|
+
"saturate",
|
686
|
+
"sepia",
|
687
|
+
"scale",
|
688
|
+
"scale3d",
|
689
|
+
"scaleX",
|
690
|
+
"scaleY",
|
691
|
+
"scaleZ",
|
692
|
+
"skew",
|
693
|
+
"skewX",
|
694
|
+
"skewY",
|
695
|
+
"symbols",
|
696
|
+
"translate",
|
697
|
+
"translate3d",
|
698
|
+
"translateX",
|
699
|
+
"translateY",
|
700
|
+
"translateZ",
|
701
|
+
])
|
702
|
+
|
703
|
+
SHORTHAND_CSS_PROPERTIES = Set.new([
|
704
|
+
"background",
|
705
|
+
"border",
|
706
|
+
"margin",
|
707
|
+
"padding",
|
708
|
+
])
|
709
|
+
|
710
|
+
ACCEPTABLE_SVG_PROPERTIES = Set.new([
|
711
|
+
"fill",
|
712
|
+
"fill-opacity",
|
713
|
+
"fill-rule",
|
714
|
+
"stroke",
|
715
|
+
"stroke-width",
|
716
|
+
"stroke-linecap",
|
717
|
+
"stroke-linejoin",
|
718
|
+
"stroke-opacity",
|
719
|
+
])
|
720
|
+
|
721
|
+
PROTOCOL_SEPARATOR = /:|(�*58)|(p)|(�*3a)|(%|%)3A/i
|
722
|
+
|
723
|
+
ACCEPTABLE_PROTOCOLS = Set.new([
|
724
|
+
"afs",
|
725
|
+
"aim",
|
726
|
+
"callto",
|
727
|
+
"data",
|
728
|
+
"ed2k",
|
729
|
+
"feed",
|
730
|
+
"ftp",
|
731
|
+
"gopher",
|
732
|
+
"http",
|
733
|
+
"https",
|
734
|
+
"irc",
|
735
|
+
"line",
|
736
|
+
"mailto",
|
737
|
+
"news",
|
738
|
+
"nntp",
|
739
|
+
"rsync",
|
740
|
+
"rtsp",
|
741
|
+
"sftp",
|
742
|
+
"ssh",
|
743
|
+
"tag",
|
744
|
+
"tel",
|
745
|
+
"telnet",
|
746
|
+
"urn",
|
747
|
+
"webcal",
|
748
|
+
"xmpp",
|
749
|
+
])
|
750
|
+
|
751
|
+
ACCEPTABLE_URI_DATA_MEDIATYPES = Set.new([
|
752
|
+
"image/gif",
|
753
|
+
"image/jpeg",
|
754
|
+
"image/png",
|
755
|
+
"image/svg+xml",
|
756
|
+
"text/css",
|
757
|
+
"text/plain",
|
758
|
+
])
|
759
|
+
|
760
|
+
# subclasses may define their own versions of these constants
|
761
|
+
ALLOWED_ELEMENTS = ACCEPTABLE_ELEMENTS + MATHML_ELEMENTS + SVG_ELEMENTS
|
762
|
+
ALLOWED_ATTRIBUTES = ACCEPTABLE_ATTRIBUTES + MATHML_ATTRIBUTES + SVG_ATTRIBUTES
|
763
|
+
ALLOWED_CSS_PROPERTIES = ACCEPTABLE_CSS_PROPERTIES
|
764
|
+
ALLOWED_CSS_KEYWORDS = ACCEPTABLE_CSS_KEYWORDS
|
765
|
+
ALLOWED_CSS_FUNCTIONS = ACCEPTABLE_CSS_FUNCTIONS
|
766
|
+
ALLOWED_SVG_PROPERTIES = ACCEPTABLE_SVG_PROPERTIES
|
767
|
+
ALLOWED_PROTOCOLS = ACCEPTABLE_PROTOCOLS
|
768
|
+
ALLOWED_URI_DATA_MEDIATYPES = ACCEPTABLE_URI_DATA_MEDIATYPES
|
769
|
+
|
770
|
+
VOID_ELEMENTS = Set.new([
|
771
|
+
"area",
|
772
|
+
"base",
|
773
|
+
"br",
|
774
|
+
"col",
|
775
|
+
"embed",
|
776
|
+
"hr",
|
777
|
+
"img",
|
778
|
+
"input",
|
779
|
+
"link",
|
780
|
+
"meta",
|
781
|
+
"param",
|
782
|
+
])
|
783
|
+
|
784
|
+
# additional tags we should consider safe since we have libxml2 fixing up our documents.
|
785
|
+
TAGS_SAFE_WITH_LIBXML2 = Set.new([
|
786
|
+
"body",
|
787
|
+
"head",
|
788
|
+
"html",
|
789
|
+
])
|
790
|
+
ALLOWED_ELEMENTS_WITH_LIBXML2 = ALLOWED_ELEMENTS + TAGS_SAFE_WITH_LIBXML2
|
791
|
+
end
|
792
|
+
|
793
|
+
WhiteList = SafeList
|
794
|
+
if Object.respond_to?(:deprecate_constant)
|
795
|
+
deprecate_constant :WhiteList
|
796
|
+
end
|
797
|
+
|
798
|
+
::Loofah::MetaHelpers.add_downcased_set_members_to_all_set_constants ::Loofah::HTML5::SafeList
|
799
|
+
end
|
800
|
+
end
|