rails-html-sanitizer 1.0.3 → 1.3.0
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 +5 -5
- data/CHANGELOG.md +37 -0
- data/MIT-LICENSE +23 -0
- data/README.md +15 -17
- data/lib/rails-html-sanitizer.rb +7 -3
- data/lib/rails/html/sanitizer.rb +26 -23
- data/lib/rails/html/sanitizer/version.rb +1 -1
- data/lib/rails/html/scrubbers.rb +25 -22
- data/test/sanitizer_test.rb +82 -44
- metadata +9 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8eba1aac52c80be280f186c5d378150709b7d4cd2a5d5b2367e6d2c036648d52
|
4
|
+
data.tar.gz: 96408eae2efee778a704f7caf246b64868a63bfdbbb81905b294bcca731a9289
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4209cebc841299143a466143f4b776461fc1cc8bba112dc603e86835b68ee44a800566f64224b27f5a45d164d0b004049b228dc405c3de59068800ec7a5d564
|
7
|
+
data.tar.gz: c899472b8dffe9f9fd4d15ae4739f07a775d74b9ed14143beb688bb546b6a82ec469add036747b81aff33510e6e241379e21458cb39d9b2a8e797824066e24e5
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,40 @@
|
|
1
|
+
## 1.3.0
|
2
|
+
|
3
|
+
* Address deprecations in Loofah 2.3.0.
|
4
|
+
|
5
|
+
*Josh Goodall*
|
6
|
+
|
7
|
+
## 1.2.0
|
8
|
+
|
9
|
+
* Remove needless `white_list_sanitizer` deprecation.
|
10
|
+
|
11
|
+
By deprecating this, we were forcing Rails 5.2 to be updated or spew
|
12
|
+
deprecations that users could do nothing about.
|
13
|
+
|
14
|
+
That's pointless and I'm sorry for adding that!
|
15
|
+
|
16
|
+
Now there's no deprecation warning and Rails 5.2 works out of the box, while
|
17
|
+
Rails 6 can use the updated naming.
|
18
|
+
|
19
|
+
*Kasper Timm Hansen*
|
20
|
+
|
21
|
+
## 1.1.0
|
22
|
+
|
23
|
+
* Add `safe_list_sanitizer` and deprecate `white_list_sanitizer` to be removed
|
24
|
+
in 1.2.0. https://github.com/rails/rails-html-sanitizer/pull/87
|
25
|
+
|
26
|
+
*Juanito Fatas*
|
27
|
+
|
28
|
+
* Remove `href` from LinkScrubber's `tags` as it's not an element.
|
29
|
+
https://github.com/rails/rails-html-sanitizer/pull/92
|
30
|
+
|
31
|
+
*Juanito Fatas*
|
32
|
+
|
33
|
+
* Explain that we don't need to bump Loofah here if there's CVEs.
|
34
|
+
https://github.com/rails/rails-html-sanitizer/commit/d4d823c617fdd0064956047f7fbf23fff305a69b
|
35
|
+
|
36
|
+
*Kasper Timm Hansen*
|
37
|
+
|
1
38
|
## 1.0.1
|
2
39
|
|
3
40
|
* Added support for Rails 4.2.0.beta2 and above
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Copyright (c) 2013-2015 Rafael Mendonça França, Kasper Timm Hansen
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
data/README.md
CHANGED
@@ -41,22 +41,22 @@ link_sanitizer.sanitize('<a href="example.com">Only the link text will be kept.<
|
|
41
41
|
# => Only the link text will be kept.
|
42
42
|
```
|
43
43
|
|
44
|
-
####
|
44
|
+
#### SafeListSanitizer
|
45
45
|
|
46
46
|
```ruby
|
47
|
-
|
47
|
+
safe_list_sanitizer = Rails::Html::SafeListSanitizer.new
|
48
48
|
|
49
|
-
# sanitize via an extensive
|
50
|
-
|
49
|
+
# sanitize via an extensive safe list of allowed elements
|
50
|
+
safe_list_sanitizer.sanitize(@article.body)
|
51
51
|
|
52
|
-
#
|
53
|
-
|
52
|
+
# safe list only the supplied tags and attributes
|
53
|
+
safe_list_sanitizer.sanitize(@article.body, tags: %w(table tr td), attributes: %w(id class style))
|
54
54
|
|
55
|
-
#
|
56
|
-
|
55
|
+
# safe list via a custom scrubber
|
56
|
+
safe_list_sanitizer.sanitize(@article.body, scrubber: ArticleScrubber.new)
|
57
57
|
|
58
|
-
#
|
59
|
-
|
58
|
+
# safe list sanitizer can also sanitize css
|
59
|
+
safe_list_sanitizer.sanitize_css('background-color: #000;')
|
60
60
|
```
|
61
61
|
|
62
62
|
### Scrubbers
|
@@ -99,17 +99,15 @@ You can also create custom scrubbers in your application if you want to.
|
|
99
99
|
|
100
100
|
```ruby
|
101
101
|
class CommentScrubber < Rails::Html::PermitScrubber
|
102
|
-
def
|
103
|
-
|
102
|
+
def initialize
|
103
|
+
super
|
104
|
+
self.tags = %w( form script comment blockquote )
|
105
|
+
self.attributes = %w( style )
|
104
106
|
end
|
105
107
|
|
106
108
|
def skip_node?(node)
|
107
109
|
node.text?
|
108
110
|
end
|
109
|
-
|
110
|
-
def scrub_attribute?(name)
|
111
|
-
name == "style"
|
112
|
-
end
|
113
111
|
end
|
114
112
|
```
|
115
113
|
|
@@ -129,7 +127,7 @@ Loofah is what underlies the sanitizers and scrubbers of rails-html-sanitizer.
|
|
129
127
|
- [Loofah and Loofah Scrubbers](https://github.com/flavorjones/loofah)
|
130
128
|
|
131
129
|
The `node` argument passed to some methods in a custom scrubber is an instance of `Nokogiri::XML::Node`.
|
132
|
-
- [`Nokogiri::XML::Node`](
|
130
|
+
- [`Nokogiri::XML::Node`](https://nokogiri.org/rdoc/Nokogiri/XML/Node.html)
|
133
131
|
- [Nokogiri](http://nokogiri.org)
|
134
132
|
|
135
133
|
## Contributing to Rails Html Sanitizers
|
data/lib/rails-html-sanitizer.rb
CHANGED
@@ -15,8 +15,12 @@ module Rails
|
|
15
15
|
Html::LinkSanitizer
|
16
16
|
end
|
17
17
|
|
18
|
+
def safe_list_sanitizer
|
19
|
+
Html::SafeListSanitizer
|
20
|
+
end
|
21
|
+
|
18
22
|
def white_list_sanitizer
|
19
|
-
|
23
|
+
safe_list_sanitizer
|
20
24
|
end
|
21
25
|
end
|
22
26
|
end
|
@@ -34,7 +38,7 @@ module ActionView
|
|
34
38
|
# end
|
35
39
|
#
|
36
40
|
def sanitized_allowed_tags=(tags)
|
37
|
-
sanitizer_vendor.
|
41
|
+
sanitizer_vendor.safe_list_sanitizer.allowed_tags = tags
|
38
42
|
end
|
39
43
|
|
40
44
|
# Replaces the allowed HTML attributes for the +sanitize+ helper.
|
@@ -44,7 +48,7 @@ module ActionView
|
|
44
48
|
# end
|
45
49
|
#
|
46
50
|
def sanitized_allowed_attributes=(attributes)
|
47
|
-
sanitizer_vendor.
|
51
|
+
sanitizer_vendor.safe_list_sanitizer.allowed_attributes = attributes
|
48
52
|
end
|
49
53
|
|
50
54
|
[:protocol_separator,
|
data/lib/rails/html/sanitizer.rb
CHANGED
@@ -40,15 +40,16 @@ module Rails
|
|
40
40
|
end
|
41
41
|
|
42
42
|
# === Rails::Html::LinkSanitizer
|
43
|
-
# Removes a tags and href attributes leaving only the link text
|
43
|
+
# Removes +a+ tags and +href+ attributes leaving only the link text.
|
44
44
|
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
45
|
+
# link_sanitizer = Rails::Html::LinkSanitizer.new
|
46
|
+
# link_sanitizer.sanitize('<a href="example.com">Only the link text will be kept.</a>')
|
47
|
+
#
|
48
|
+
# => 'Only the link text will be kept.'
|
48
49
|
class LinkSanitizer < Sanitizer
|
49
50
|
def initialize
|
50
51
|
@link_scrubber = TargetScrubber.new
|
51
|
-
@link_scrubber.tags = %w(a
|
52
|
+
@link_scrubber.tags = %w(a)
|
52
53
|
@link_scrubber.attributes = %w(href)
|
53
54
|
end
|
54
55
|
|
@@ -57,11 +58,11 @@ module Rails
|
|
57
58
|
end
|
58
59
|
end
|
59
60
|
|
60
|
-
# === Rails::Html::
|
61
|
-
# Sanitizes html and css from an extensive
|
61
|
+
# === Rails::Html::SafeListSanitizer
|
62
|
+
# Sanitizes html and css from an extensive safe list (see link further down).
|
62
63
|
#
|
63
64
|
# === Whitespace
|
64
|
-
# We can't make any
|
65
|
+
# We can't make any guarantees about whitespace being kept or stripped.
|
65
66
|
# Loofah uses Nokogiri, which wraps either a C or Java parser for the
|
66
67
|
# respective Ruby implementation.
|
67
68
|
# Those two parsers determine how whitespace is ultimately handled.
|
@@ -72,34 +73,34 @@ module Rails
|
|
72
73
|
# so automatically.
|
73
74
|
#
|
74
75
|
# === Options
|
75
|
-
# Sanitizes both html and css via the
|
76
|
-
# https://github.com/flavorjones/loofah/blob/master/lib/loofah/html5/
|
76
|
+
# Sanitizes both html and css via the safe lists found here:
|
77
|
+
# https://github.com/flavorjones/loofah/blob/master/lib/loofah/html5/safelist.rb
|
77
78
|
#
|
78
|
-
#
|
79
|
-
# the
|
79
|
+
# SafeListSanitizer also accepts options to configure
|
80
|
+
# the safe list used when sanitizing html.
|
80
81
|
# There's a class level option:
|
81
|
-
# Rails::Html::
|
82
|
-
# Rails::Html::
|
82
|
+
# Rails::Html::SafeListSanitizer.allowed_tags = %w(table tr td)
|
83
|
+
# Rails::Html::SafeListSanitizer.allowed_attributes = %w(id class style)
|
83
84
|
#
|
84
85
|
# Tags and attributes can also be passed to +sanitize+.
|
85
86
|
# Passed options take precedence over the class level options.
|
86
87
|
#
|
87
88
|
# === Examples
|
88
|
-
#
|
89
|
+
# safe_list_sanitizer = Rails::Html::SafeListSanitizer.new
|
89
90
|
#
|
90
91
|
# Sanitize css doesn't take options
|
91
|
-
#
|
92
|
+
# safe_list_sanitizer.sanitize_css('background-color: #000;')
|
92
93
|
#
|
93
|
-
# Default: sanitize via a extensive
|
94
|
-
#
|
94
|
+
# Default: sanitize via a extensive safe list of allowed elements
|
95
|
+
# safe_list_sanitizer.sanitize(@article.body)
|
95
96
|
#
|
96
|
-
#
|
97
|
-
#
|
97
|
+
# Safe list via the supplied tags and attributes
|
98
|
+
# safe_list_sanitizer.sanitize(@article.body, tags: %w(table tr td),
|
98
99
|
# attributes: %w(id class style))
|
99
100
|
#
|
100
|
-
#
|
101
|
-
#
|
102
|
-
class
|
101
|
+
# Safe list via a custom scrubber
|
102
|
+
# safe_list_sanitizer.sanitize(@article.body, scrubber: ArticleScrubber.new)
|
103
|
+
class SafeListSanitizer < Sanitizer
|
103
104
|
class << self
|
104
105
|
attr_accessor :allowed_tags
|
105
106
|
attr_accessor :allowed_attributes
|
@@ -148,5 +149,7 @@ module Rails
|
|
148
149
|
options[:attributes] || self.class.allowed_attributes
|
149
150
|
end
|
150
151
|
end
|
152
|
+
|
153
|
+
WhiteListSanitizer = SafeListSanitizer
|
151
154
|
end
|
152
155
|
end
|
data/lib/rails/html/scrubbers.rb
CHANGED
@@ -2,9 +2,9 @@ module Rails
|
|
2
2
|
module Html
|
3
3
|
# === Rails::Html::PermitScrubber
|
4
4
|
#
|
5
|
-
# Rails::Html::PermitScrubber allows you to permit only your own tags and/or attributes.
|
5
|
+
# +Rails::Html::PermitScrubber+ allows you to permit only your own tags and/or attributes.
|
6
6
|
#
|
7
|
-
# Rails::Html::PermitScrubber can be subclassed to determine:
|
7
|
+
# +Rails::Html::PermitScrubber+ can be subclassed to determine:
|
8
8
|
# - When a node should be skipped via +skip_node?+.
|
9
9
|
# - When a node is allowed via +allowed_node?+.
|
10
10
|
# - When an attribute should be scrubbed via +scrub_attribute?+.
|
@@ -27,22 +27,23 @@ module Rails
|
|
27
27
|
# If set, attributes excluded will be removed.
|
28
28
|
# If not, attributes are removed based on Loofahs +HTML5::Scrub.scrub_attributes+.
|
29
29
|
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
30
|
+
# class CommentScrubber < Html::PermitScrubber
|
31
|
+
# def initialize
|
32
|
+
# super
|
33
|
+
# self.tags = %w(form script comment blockquote)
|
34
|
+
# end
|
34
35
|
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
36
|
+
# def skip_node?(node)
|
37
|
+
# node.text?
|
38
|
+
# end
|
38
39
|
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
40
|
+
# def scrub_attribute?(name)
|
41
|
+
# name == "style"
|
42
|
+
# end
|
43
|
+
# end
|
43
44
|
#
|
44
|
-
# See the documentation for Nokogiri::XML::Node to understand what's possible
|
45
|
-
# with nodes:
|
45
|
+
# See the documentation for +Nokogiri::XML::Node+ to understand what's possible
|
46
|
+
# with nodes: https://nokogiri.org/rdoc/Nokogiri/XML/Node.html
|
46
47
|
class PermitScrubber < Loofah::Scrubber
|
47
48
|
attr_reader :tags, :attributes
|
48
49
|
|
@@ -137,28 +138,30 @@ module Rails
|
|
137
138
|
attr_node.node_name
|
138
139
|
end
|
139
140
|
|
140
|
-
if Loofah::HTML5::
|
141
|
+
if Loofah::HTML5::SafeList::ATTR_VAL_IS_URI.include?(attr_name)
|
141
142
|
# this block lifted nearly verbatim from HTML5 sanitization
|
142
143
|
val_unescaped = CGI.unescapeHTML(attr_node.value).gsub(Loofah::HTML5::Scrub::CONTROL_CHARACTERS,'').downcase
|
143
|
-
if val_unescaped =~ /^[a-z0-9][-+.a-z0-9]*:/ && ! Loofah::HTML5::
|
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])
|
144
145
|
attr_node.remove
|
145
146
|
end
|
146
147
|
end
|
147
|
-
if Loofah::HTML5::
|
148
|
+
if Loofah::HTML5::SafeList::SVG_ATTR_VAL_ALLOWS_REF.include?(attr_name)
|
148
149
|
attr_node.value = attr_node.value.gsub(/url\s*\(\s*[^#\s][^)]+?\)/m, ' ') if attr_node.value
|
149
150
|
end
|
150
|
-
if Loofah::HTML5::
|
151
|
+
if Loofah::HTML5::SafeList::SVG_ALLOW_LOCAL_HREF.include?(node.name) && attr_name == 'xlink:href' && attr_node.value =~ /^\s*[^#\s].*/m
|
151
152
|
attr_node.remove
|
152
153
|
end
|
153
154
|
|
154
155
|
node.remove_attribute(attr_node.name) if attr_name == 'src' && attr_node.value !~ /[^[:space:]]/
|
156
|
+
|
157
|
+
Loofah::HTML5::Scrub.force_correct_attribute_escaping! node
|
155
158
|
end
|
156
159
|
end
|
157
160
|
|
158
161
|
# === Rails::Html::TargetScrubber
|
159
162
|
#
|
160
|
-
# Where Rails::Html::PermitScrubber picks out tags and attributes to permit in
|
161
|
-
# sanitization, Rails::Html::TargetScrubber targets them for removal.
|
163
|
+
# Where +Rails::Html::PermitScrubber+ picks out tags and attributes to permit in
|
164
|
+
# sanitization, +Rails::Html::TargetScrubber+ targets them for removal.
|
162
165
|
#
|
163
166
|
# +tags=+
|
164
167
|
# If set, elements included will be stripped.
|
@@ -177,7 +180,7 @@ module Rails
|
|
177
180
|
|
178
181
|
# === Rails::Html::TextOnlyScrubber
|
179
182
|
#
|
180
|
-
# Rails::Html::TextOnlyScrubber allows you to permit text nodes.
|
183
|
+
# +Rails::Html::TextOnlyScrubber+ allows you to permit text nodes.
|
181
184
|
#
|
182
185
|
# Unallowed elements will be stripped, i.e. element is removed but its subtree kept.
|
183
186
|
class TextOnlyScrubber < Loofah::Scrubber
|
data/test/sanitizer_test.rb
CHANGED
@@ -12,12 +12,12 @@ class SanitizersTest < Minitest::Test
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def test_sanitize_nested_script
|
15
|
-
sanitizer = Rails::Html::
|
15
|
+
sanitizer = Rails::Html::SafeListSanitizer.new
|
16
16
|
assert_equal '<script>alert("XSS");</script>', sanitizer.sanitize('<script><script></script>alert("XSS");<script><</script>/</script><script>script></script>', tags: %w(em))
|
17
17
|
end
|
18
18
|
|
19
19
|
def test_sanitize_nested_script_in_style
|
20
|
-
sanitizer = Rails::Html::
|
20
|
+
sanitizer = Rails::Html::SafeListSanitizer.new
|
21
21
|
assert_equal '<script>alert("XSS");</script>', sanitizer.sanitize('<style><script></style>alert("XSS");<style><</style>/</style><style>script></style>', tags: %w(em))
|
22
22
|
end
|
23
23
|
|
@@ -33,7 +33,7 @@ class SanitizersTest < Minitest::Test
|
|
33
33
|
assert_equal %(<h1>hello </h1>), xpath_sanitize(html, xpaths: %w(.//script))
|
34
34
|
end
|
35
35
|
|
36
|
-
def
|
36
|
+
def test_remove_xpaths_removes_all_occurrences_of_xpath
|
37
37
|
html = %(<section><header><script>code!</script></header><p>hello <script>code!</script></p></section>)
|
38
38
|
assert_equal %(<section><header></header><p>hello </p></section>), xpath_sanitize(html, xpaths: %w(.//script))
|
39
39
|
end
|
@@ -58,11 +58,11 @@ class SanitizersTest < Minitest::Test
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def test_strip_invalid_html
|
61
|
-
assert_equal "", full_sanitize("<<<bad html")
|
61
|
+
assert_equal "<<", full_sanitize("<<<bad html")
|
62
62
|
end
|
63
63
|
|
64
64
|
def test_strip_nested_tags
|
65
|
-
expected = "
|
65
|
+
expected = "Wei<a onclick='alert(document.cookie);'/>rdos"
|
66
66
|
input = "Wei<<a>a onclick='alert(document.cookie);'</a>/>rdos"
|
67
67
|
assert_equal expected, full_sanitize(input)
|
68
68
|
end
|
@@ -74,7 +74,7 @@ class SanitizersTest < Minitest::Test
|
|
74
74
|
assert_equal expected, full_sanitize(input)
|
75
75
|
end
|
76
76
|
|
77
|
-
def
|
77
|
+
def test_remove_unclosed_tags
|
78
78
|
assert_equal "This is ", full_sanitize("This is <-- not\n a comment here.")
|
79
79
|
end
|
80
80
|
|
@@ -87,7 +87,9 @@ class SanitizersTest < Minitest::Test
|
|
87
87
|
end
|
88
88
|
|
89
89
|
def test_strip_blank_string
|
90
|
-
|
90
|
+
assert_nil full_sanitize(nil)
|
91
|
+
assert_equal "", full_sanitize("")
|
92
|
+
assert_equal " ", full_sanitize(" ")
|
91
93
|
end
|
92
94
|
|
93
95
|
def test_strip_tags_with_plaintext
|
@@ -98,8 +100,8 @@ class SanitizersTest < Minitest::Test
|
|
98
100
|
assert_equal "This is a test.", full_sanitize("<p>This <u>is<u> a <a href='test.html'><strong>test</strong></a>.</p>")
|
99
101
|
end
|
100
102
|
|
101
|
-
def
|
102
|
-
assert_equal "", full_sanitize("<<<bad html>")
|
103
|
+
def test_escape_tags_with_many_open_quotes
|
104
|
+
assert_equal "<<", full_sanitize("<<<bad html>")
|
103
105
|
end
|
104
106
|
|
105
107
|
def test_strip_tags_with_sentence
|
@@ -123,7 +125,7 @@ class SanitizersTest < Minitest::Test
|
|
123
125
|
end
|
124
126
|
|
125
127
|
def test_strip_links_with_tags_in_tags
|
126
|
-
expected = "a href='hello'>all <b>day</b> long
|
128
|
+
expected = "<a href='hello'>all <b>day</b> long</a>"
|
127
129
|
input = "<<a>a href='hello'>all <b>day</b> long<</A>/a>"
|
128
130
|
assert_equal expected, link_sanitize(input)
|
129
131
|
end
|
@@ -152,10 +154,6 @@ class SanitizersTest < Minitest::Test
|
|
152
154
|
assert_equal "Magic", link_sanitize("<a href='http://www.rubyonrails.com/'>Mag<a href='http://www.ruby-lang.org/'>ic")
|
153
155
|
end
|
154
156
|
|
155
|
-
def test_strip_links_with_a_tag_in_href
|
156
|
-
assert_equal "FrrFox", link_sanitize("<href onlclick='steal()'>FrrFox</a></href>")
|
157
|
-
end
|
158
|
-
|
159
157
|
def test_sanitize_form
|
160
158
|
assert_sanitized "<form action=\"/foo/bar\" method=\"post\"><input></form>", ''
|
161
159
|
end
|
@@ -183,7 +181,7 @@ class SanitizersTest < Minitest::Test
|
|
183
181
|
assert_sanitized raw, %{src="javascript:bang" <img width="5">foo</img>, <span>bar</span>}
|
184
182
|
end
|
185
183
|
|
186
|
-
tags = Loofah::HTML5::
|
184
|
+
tags = Loofah::HTML5::SafeList::ALLOWED_ELEMENTS - %w(script form)
|
187
185
|
tags.each do |tag_name|
|
188
186
|
define_method "test_should_allow_#{tag_name}_tag" do
|
189
187
|
scope_allowed_tags(tags) do
|
@@ -253,38 +251,38 @@ class SanitizersTest < Minitest::Test
|
|
253
251
|
|
254
252
|
def test_should_allow_custom_tags
|
255
253
|
text = "<u>foo</u>"
|
256
|
-
assert_equal text,
|
254
|
+
assert_equal text, safe_list_sanitize(text, tags: %w(u))
|
257
255
|
end
|
258
256
|
|
259
257
|
def test_should_allow_only_custom_tags
|
260
258
|
text = "<u>foo</u> with <i>bar</i>"
|
261
|
-
assert_equal "<u>foo</u> with bar",
|
259
|
+
assert_equal "<u>foo</u> with bar", safe_list_sanitize(text, tags: %w(u))
|
262
260
|
end
|
263
261
|
|
264
262
|
def test_should_allow_custom_tags_with_attributes
|
265
263
|
text = %(<blockquote cite="http://example.com/">foo</blockquote>)
|
266
|
-
assert_equal text,
|
264
|
+
assert_equal text, safe_list_sanitize(text)
|
267
265
|
end
|
268
266
|
|
269
267
|
def test_should_allow_custom_tags_with_custom_attributes
|
270
268
|
text = %(<blockquote foo="bar">Lorem ipsum</blockquote>)
|
271
|
-
assert_equal text,
|
269
|
+
assert_equal text, safe_list_sanitize(text, attributes: ['foo'])
|
272
270
|
end
|
273
271
|
|
274
272
|
def test_scrub_style_if_style_attribute_option_is_passed
|
275
273
|
input = '<p style="color: #000; background-image: url(http://www.ragingplatypus.com/i/cam-full.jpg);"></p>'
|
276
|
-
assert_equal '<p style="color: #000;"></p>',
|
274
|
+
assert_equal '<p style="color: #000;"></p>', safe_list_sanitize(input, attributes: %w(style))
|
277
275
|
end
|
278
276
|
|
279
277
|
def test_should_raise_argument_error_if_tags_is_not_enumerable
|
280
278
|
assert_raises ArgumentError do
|
281
|
-
|
279
|
+
safe_list_sanitize('<a>some html</a>', tags: 'foo')
|
282
280
|
end
|
283
281
|
end
|
284
282
|
|
285
283
|
def test_should_raise_argument_error_if_attributes_is_not_enumerable
|
286
284
|
assert_raises ArgumentError do
|
287
|
-
|
285
|
+
safe_list_sanitize('<a>some html</a>', attributes: 'foo')
|
288
286
|
end
|
289
287
|
end
|
290
288
|
|
@@ -293,7 +291,7 @@ class SanitizersTest < Minitest::Test
|
|
293
291
|
def scrubber.scrub(node); node.name = 'h1'; end
|
294
292
|
|
295
293
|
assert_raises Loofah::ScrubberNotFound do
|
296
|
-
|
294
|
+
safe_list_sanitize('<a>some html</a>', scrubber: scrubber)
|
297
295
|
end
|
298
296
|
end
|
299
297
|
|
@@ -302,19 +300,19 @@ class SanitizersTest < Minitest::Test
|
|
302
300
|
def scrubber.scrub(node); node.name = 'h1'; end
|
303
301
|
|
304
302
|
html = "<script>hello!</script>"
|
305
|
-
assert_equal "<h1>hello!</h1>",
|
303
|
+
assert_equal "<h1>hello!</h1>", safe_list_sanitize(html, scrubber: scrubber)
|
306
304
|
end
|
307
305
|
|
308
306
|
def test_should_accept_loofah_scrubber_that_wraps_a_block
|
309
307
|
scrubber = Loofah::Scrubber.new { |node| node.name = 'h1' }
|
310
308
|
html = "<script>hello!</script>"
|
311
|
-
assert_equal "<h1>hello!</h1>",
|
309
|
+
assert_equal "<h1>hello!</h1>", safe_list_sanitize(html, scrubber: scrubber)
|
312
310
|
end
|
313
311
|
|
314
312
|
def test_custom_scrubber_takes_precedence_over_other_options
|
315
313
|
scrubber = Loofah::Scrubber.new { |node| node.name = 'h1' }
|
316
314
|
html = "<script>hello!</script>"
|
317
|
-
assert_equal "<h1>hello!</h1>",
|
315
|
+
assert_equal "<h1>hello!</h1>", safe_list_sanitize(html, scrubber: scrubber, tags: ['foo'])
|
318
316
|
end
|
319
317
|
|
320
318
|
[%w(img src), %w(a href)].each do |(tag, attr)|
|
@@ -360,7 +358,7 @@ class SanitizersTest < Minitest::Test
|
|
360
358
|
end
|
361
359
|
|
362
360
|
def test_should_sanitize_script_tag_with_multiple_open_brackets
|
363
|
-
assert_sanitized %(<<SCRIPT>alert("XSS");//<</SCRIPT>), "alert(\"XSS\")
|
361
|
+
assert_sanitized %(<<SCRIPT>alert("XSS");//<</SCRIPT>), "<alert(\"XSS\");//<"
|
364
362
|
assert_sanitized %(<iframe src=http://ha.ckers.org/scriptlet.html\n<a), ""
|
365
363
|
end
|
366
364
|
|
@@ -383,13 +381,13 @@ class SanitizersTest < Minitest::Test
|
|
383
381
|
|
384
382
|
def test_should_sanitize_illegal_style_properties
|
385
383
|
raw = %(display:block; position:absolute; left:0; top:0; width:100%; height:100%; z-index:1; background-color:black; background-image:url(http://www.ragingplatypus.com/i/cam-full.jpg); background-x:center; background-y:center; background-repeat:repeat;)
|
386
|
-
expected = %(display:
|
384
|
+
expected = %(display:block;width:100%;height:100%;background-color:black;background-x:center;background-y:center;)
|
387
385
|
assert_equal expected, sanitize_css(raw)
|
388
386
|
end
|
389
387
|
|
390
388
|
def test_should_sanitize_with_trailing_space
|
391
389
|
raw = "display:block; "
|
392
|
-
expected = "display:
|
390
|
+
expected = "display:block;"
|
393
391
|
assert_equal expected, sanitize_css(raw)
|
394
392
|
end
|
395
393
|
|
@@ -466,7 +464,7 @@ class SanitizersTest < Minitest::Test
|
|
466
464
|
end
|
467
465
|
|
468
466
|
def test_sanitize_ascii_8bit_string
|
469
|
-
|
467
|
+
safe_list_sanitize('<a>hello</a>'.encode('ASCII-8BIT')).tap do |sanitized|
|
470
468
|
assert_equal '<a>hello</a>', sanitized
|
471
469
|
assert_equal Encoding::UTF_8, sanitized.encoding
|
472
470
|
end
|
@@ -479,7 +477,47 @@ class SanitizersTest < Minitest::Test
|
|
479
477
|
|
480
478
|
def test_allow_data_attribute_if_requested
|
481
479
|
text = %(<a data-foo="foo">foo</a>)
|
482
|
-
assert_equal %(<a data-foo="foo">foo</a>),
|
480
|
+
assert_equal %(<a data-foo="foo">foo</a>), safe_list_sanitize(text, attributes: ['data-foo'])
|
481
|
+
end
|
482
|
+
|
483
|
+
def test_uri_escaping_of_href_attr_in_a_tag_in_safe_list_sanitizer
|
484
|
+
skip if RUBY_VERSION < "2.3"
|
485
|
+
|
486
|
+
html = %{<a href='examp<!--" unsafeattr=foo()>-->le.com'>test</a>}
|
487
|
+
|
488
|
+
text = safe_list_sanitize(html)
|
489
|
+
|
490
|
+
assert_equal %{<a href=\"examp<!--%22%20unsafeattr=foo()>-->le.com\">test</a>}, text
|
491
|
+
end
|
492
|
+
|
493
|
+
def test_uri_escaping_of_src_attr_in_a_tag_in_safe_list_sanitizer
|
494
|
+
skip if RUBY_VERSION < "2.3"
|
495
|
+
|
496
|
+
html = %{<a src='examp<!--" unsafeattr=foo()>-->le.com'>test</a>}
|
497
|
+
|
498
|
+
text = safe_list_sanitize(html)
|
499
|
+
|
500
|
+
assert_equal %{<a src=\"examp<!--%22%20unsafeattr=foo()>-->le.com\">test</a>}, text
|
501
|
+
end
|
502
|
+
|
503
|
+
def test_uri_escaping_of_name_attr_in_a_tag_in_safe_list_sanitizer
|
504
|
+
skip if RUBY_VERSION < "2.3"
|
505
|
+
|
506
|
+
html = %{<a name='examp<!--" unsafeattr=foo()>-->le.com'>test</a>}
|
507
|
+
|
508
|
+
text = safe_list_sanitize(html)
|
509
|
+
|
510
|
+
assert_equal %{<a name=\"examp<!--%22%20unsafeattr=foo()>-->le.com\">test</a>}, text
|
511
|
+
end
|
512
|
+
|
513
|
+
def test_uri_escaping_of_name_action_in_a_tag_in_safe_list_sanitizer
|
514
|
+
skip if RUBY_VERSION < "2.3"
|
515
|
+
|
516
|
+
html = %{<a action='examp<!--" unsafeattr=foo()>-->le.com'>test</a>}
|
517
|
+
|
518
|
+
text = safe_list_sanitize(html, attributes: ['action'])
|
519
|
+
|
520
|
+
assert_equal %{<a action=\"examp<!--%22%20unsafeattr=foo()>-->le.com\">test</a>}, text
|
483
521
|
end
|
484
522
|
|
485
523
|
protected
|
@@ -496,35 +534,35 @@ protected
|
|
496
534
|
Rails::Html::LinkSanitizer.new.sanitize(input, options)
|
497
535
|
end
|
498
536
|
|
499
|
-
def
|
500
|
-
Rails::Html::
|
537
|
+
def safe_list_sanitize(input, options = {})
|
538
|
+
Rails::Html::SafeListSanitizer.new.sanitize(input, options)
|
501
539
|
end
|
502
540
|
|
503
541
|
def assert_sanitized(input, expected = nil)
|
504
542
|
if input
|
505
|
-
assert_dom_equal expected || input,
|
543
|
+
assert_dom_equal expected || input, safe_list_sanitize(input)
|
506
544
|
else
|
507
|
-
assert_nil
|
545
|
+
assert_nil safe_list_sanitize(input)
|
508
546
|
end
|
509
547
|
end
|
510
548
|
|
511
549
|
def sanitize_css(input)
|
512
|
-
Rails::Html::
|
550
|
+
Rails::Html::SafeListSanitizer.new.sanitize_css(input)
|
513
551
|
end
|
514
552
|
|
515
553
|
def scope_allowed_tags(tags)
|
516
|
-
old_tags = Rails::Html::
|
517
|
-
Rails::Html::
|
518
|
-
yield Rails::Html::
|
554
|
+
old_tags = Rails::Html::SafeListSanitizer.allowed_tags
|
555
|
+
Rails::Html::SafeListSanitizer.allowed_tags = tags
|
556
|
+
yield Rails::Html::SafeListSanitizer.new
|
519
557
|
ensure
|
520
|
-
Rails::Html::
|
558
|
+
Rails::Html::SafeListSanitizer.allowed_tags = old_tags
|
521
559
|
end
|
522
560
|
|
523
561
|
def scope_allowed_attributes(attributes)
|
524
|
-
old_attributes = Rails::Html::
|
525
|
-
Rails::Html::
|
526
|
-
yield Rails::Html::
|
562
|
+
old_attributes = Rails::Html::SafeListSanitizer.allowed_attributes
|
563
|
+
Rails::Html::SafeListSanitizer.allowed_attributes = attributes
|
564
|
+
yield Rails::Html::SafeListSanitizer.new
|
527
565
|
ensure
|
528
|
-
Rails::Html::
|
566
|
+
Rails::Html::SafeListSanitizer.allowed_attributes = old_attributes
|
529
567
|
end
|
530
568
|
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.0
|
4
|
+
version: 1.3.0
|
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: 2019-10-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: loofah
|
@@ -17,26 +17,26 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '2.
|
20
|
+
version: '2.3'
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: '2.
|
27
|
+
version: '2.3'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: bundler
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
|
-
- - "
|
32
|
+
- - ">="
|
33
33
|
- !ruby/object:Gem::Version
|
34
34
|
version: '1.3'
|
35
35
|
type: :development
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- - "
|
39
|
+
- - ">="
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: '1.3'
|
42
42
|
- !ruby/object:Gem::Dependency
|
@@ -90,6 +90,7 @@ extensions: []
|
|
90
90
|
extra_rdoc_files: []
|
91
91
|
files:
|
92
92
|
- CHANGELOG.md
|
93
|
+
- MIT-LICENSE
|
93
94
|
- README.md
|
94
95
|
- lib/rails-html-sanitizer.rb
|
95
96
|
- lib/rails/html/sanitizer.rb
|
@@ -116,11 +117,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
116
117
|
- !ruby/object:Gem::Version
|
117
118
|
version: '0'
|
118
119
|
requirements: []
|
119
|
-
|
120
|
-
rubygems_version: 2.5.1
|
120
|
+
rubygems_version: 3.0.3
|
121
121
|
signing_key:
|
122
122
|
specification_version: 4
|
123
123
|
summary: This gem is responsible to sanitize HTML fragments in Rails applications.
|
124
124
|
test_files:
|
125
|
-
- test/sanitizer_test.rb
|
126
125
|
- test/scrubbers_test.rb
|
126
|
+
- test/sanitizer_test.rb
|