loofah 2.2.3 → 2.9.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 +4 -4
- data/CHANGELOG.md +124 -31
- data/README.md +12 -16
- data/lib/loofah.rb +35 -18
- data/lib/loofah/elements.rb +74 -73
- data/lib/loofah/helpers.rb +18 -7
- data/lib/loofah/html/document.rb +1 -0
- data/lib/loofah/html/document_fragment.rb +4 -2
- data/lib/loofah/html5/libxml2_workarounds.rb +8 -7
- data/lib/loofah/html5/safelist.rb +819 -0
- data/lib/loofah/html5/scrub.rb +63 -46
- data/lib/loofah/instance_methods.rb +5 -3
- data/lib/loofah/metahelpers.rb +2 -1
- data/lib/loofah/scrubber.rb +8 -7
- data/lib/loofah/scrubbers.rb +12 -11
- data/lib/loofah/version.rb +5 -0
- data/lib/loofah/xml/document.rb +1 -0
- data/lib/loofah/xml/document_fragment.rb +2 -1
- metadata +40 -112
- data/.gemtest +0 -0
- data/Gemfile +0 -22
- data/Manifest.txt +0 -40
- data/Rakefile +0 -79
- data/benchmark/benchmark.rb +0 -149
- data/benchmark/fragment.html +0 -96
- data/benchmark/helper.rb +0 -73
- data/benchmark/www.slashdot.com.html +0 -2560
- data/lib/loofah/html5/whitelist.rb +0 -186
- data/test/assets/msword.html +0 -63
- data/test/assets/testdata_sanitizer_tests1.dat +0 -502
- data/test/helper.rb +0 -18
- data/test/html5/test_sanitizer.rb +0 -382
- data/test/integration/test_ad_hoc.rb +0 -204
- data/test/integration/test_helpers.rb +0 -43
- data/test/integration/test_html.rb +0 -72
- data/test/integration/test_scrubbers.rb +0 -400
- data/test/integration/test_xml.rb +0 -55
- data/test/unit/test_api.rb +0 -142
- data/test/unit/test_encoding.rb +0 -20
- data/test/unit/test_helpers.rb +0 -62
- data/test/unit/test_scrubber.rb +0 -229
- data/test/unit/test_scrubbers.rb +0 -14
data/lib/loofah/html5/scrub.rb
CHANGED
@@ -1,104 +1,122 @@
|
|
1
|
-
|
2
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "cgi"
|
3
|
+
require "crass"
|
3
4
|
|
4
5
|
module Loofah
|
5
6
|
module HTML5 # :nodoc:
|
6
7
|
module Scrub
|
7
|
-
|
8
8
|
CONTROL_CHARACTERS = /[`\u0000-\u0020\u007f\u0080-\u0101]/
|
9
|
-
CSS_KEYWORDISH = /\A(#[0-9a-
|
10
|
-
CRASS_SEMICOLON = {:
|
9
|
+
CSS_KEYWORDISH = /\A(#[0-9a-fA-F]+|rgb\(\d+%?,\d*%?,?\d*%?\)?|-?\d{0,3}\.?\d{0,10}(ch|cm|r?em|ex|in|lh|mm|pc|pt|px|Q|vmax|vmin|vw|vh|%|,|\))?)\z/
|
10
|
+
CRASS_SEMICOLON = { node: :semicolon, raw: ";" }
|
11
|
+
CSS_IMPORTANT = '!important'
|
11
12
|
|
12
13
|
class << self
|
13
|
-
|
14
|
-
|
15
|
-
::Loofah::HTML5::WhiteList::ALLOWED_ELEMENTS_WITH_LIBXML2.include? element_name
|
14
|
+
def allowed_element?(element_name)
|
15
|
+
::Loofah::HTML5::SafeList::ALLOWED_ELEMENTS_WITH_LIBXML2.include?(element_name)
|
16
16
|
end
|
17
17
|
|
18
18
|
# alternative implementation of the html5lib attribute scrubbing algorithm
|
19
|
-
def scrub_attributes
|
19
|
+
def scrub_attributes(node)
|
20
20
|
node.attribute_nodes.each do |attr_node|
|
21
21
|
attr_name = if attr_node.namespace
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
"#{attr_node.namespace.prefix}:#{attr_node.node_name}"
|
23
|
+
else
|
24
|
+
attr_node.node_name
|
25
|
+
end
|
26
26
|
|
27
27
|
if attr_name =~ /\Adata-[\w-]+\z/
|
28
28
|
next
|
29
29
|
end
|
30
30
|
|
31
|
-
unless
|
31
|
+
unless SafeList::ALLOWED_ATTRIBUTES.include?(attr_name)
|
32
32
|
attr_node.remove
|
33
33
|
next
|
34
34
|
end
|
35
35
|
|
36
|
-
if
|
36
|
+
if SafeList::ATTR_VAL_IS_URI.include?(attr_name)
|
37
37
|
# this block lifted nearly verbatim from HTML5 sanitization
|
38
|
-
val_unescaped = CGI.unescapeHTML(attr_node.value).gsub(CONTROL_CHARACTERS,
|
39
|
-
if val_unescaped =~ /^[a-z0-9][-+.a-z0-9]*:/ && !
|
38
|
+
val_unescaped = CGI.unescapeHTML(attr_node.value).gsub(CONTROL_CHARACTERS, "").downcase
|
39
|
+
if val_unescaped =~ /^[a-z0-9][-+.a-z0-9]*:/ && !SafeList::ALLOWED_PROTOCOLS.include?(val_unescaped.split(SafeList::PROTOCOL_SEPARATOR)[0])
|
40
40
|
attr_node.remove
|
41
41
|
next
|
42
|
-
elsif val_unescaped.split(
|
42
|
+
elsif val_unescaped.split(SafeList::PROTOCOL_SEPARATOR)[0] == "data"
|
43
43
|
# permit only allowed data mediatypes
|
44
|
-
mediatype = val_unescaped.split(
|
45
|
-
mediatype, _ = mediatype.split(
|
46
|
-
if mediatype && !
|
44
|
+
mediatype = val_unescaped.split(SafeList::PROTOCOL_SEPARATOR)[1]
|
45
|
+
mediatype, _ = mediatype.split(";")[0..1] if mediatype
|
46
|
+
if mediatype && !SafeList::ALLOWED_URI_DATA_MEDIATYPES.include?(mediatype)
|
47
47
|
attr_node.remove
|
48
48
|
next
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|
52
|
-
if
|
53
|
-
attr_node.value = attr_node.value.gsub(/url\s*\(\s*[^#\s][^)]+?\)/m,
|
52
|
+
if SafeList::SVG_ATTR_VAL_ALLOWS_REF.include?(attr_name)
|
53
|
+
attr_node.value = attr_node.value.gsub(/url\s*\(\s*[^#\s][^)]+?\)/m, " ") if attr_node.value
|
54
54
|
end
|
55
|
-
if
|
55
|
+
if SafeList::SVG_ALLOW_LOCAL_HREF.include?(node.name) && attr_name == "xlink:href" && attr_node.value =~ /^\s*[^#\s].*/m
|
56
56
|
attr_node.remove
|
57
57
|
next
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
scrub_css_attribute
|
61
|
+
scrub_css_attribute(node)
|
62
62
|
|
63
63
|
node.attribute_nodes.each do |attr_node|
|
64
64
|
node.remove_attribute(attr_node.name) if attr_node.value !~ /[^[:space:]]/
|
65
65
|
end
|
66
66
|
|
67
|
-
force_correct_attribute_escaping!
|
67
|
+
force_correct_attribute_escaping!(node)
|
68
68
|
end
|
69
69
|
|
70
|
-
def scrub_css_attribute
|
71
|
-
style = node.attributes[
|
70
|
+
def scrub_css_attribute(node)
|
71
|
+
style = node.attributes["style"]
|
72
72
|
style.value = scrub_css(style.value) if style
|
73
73
|
end
|
74
74
|
|
75
|
-
def scrub_css
|
76
|
-
style_tree = Crass.parse_properties
|
75
|
+
def scrub_css(style)
|
76
|
+
style_tree = Crass.parse_properties(style)
|
77
77
|
sanitized_tree = []
|
78
78
|
|
79
79
|
style_tree.each do |node|
|
80
80
|
next unless node[:node] == :property
|
81
81
|
next if node[:children].any? do |child|
|
82
|
-
[:url, :bad_url].include?(child[:node])
|
82
|
+
[:url, :bad_url].include?(child[:node])
|
83
83
|
end
|
84
|
+
|
84
85
|
name = node[:name].downcase
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
86
|
+
next unless SafeList::ALLOWED_CSS_PROPERTIES.include?(name) ||
|
87
|
+
SafeList::ALLOWED_SVG_PROPERTIES.include?(name) ||
|
88
|
+
SafeList::SHORTHAND_CSS_PROPERTIES.include?(name.split("-").first)
|
89
|
+
|
90
|
+
value = node[:children].map do |child|
|
91
|
+
case child[:node]
|
92
|
+
when :whitespace
|
93
|
+
nil
|
94
|
+
when :string
|
95
|
+
nil
|
96
|
+
when :function
|
97
|
+
if SafeList::ALLOWED_CSS_FUNCTIONS.include?(child[:name].downcase)
|
98
|
+
Crass::Parser.stringify(child)
|
99
|
+
end
|
100
|
+
when :ident
|
101
|
+
keyword = child[:value]
|
102
|
+
if !SafeList::SHORTHAND_CSS_PROPERTIES.include?(name.split("-").first) ||
|
103
|
+
SafeList::ALLOWED_CSS_KEYWORDS.include?(keyword) ||
|
104
|
+
(keyword =~ CSS_KEYWORDISH)
|
90
105
|
keyword
|
91
106
|
end
|
92
|
-
|
93
|
-
|
94
|
-
propstring = sprintf "%s:%s", name, value.join(" ")
|
95
|
-
sanitized_node = Crass.parse_properties(propstring).first
|
96
|
-
sanitized_tree << sanitized_node << CRASS_SEMICOLON
|
107
|
+
else
|
108
|
+
child[:raw]
|
97
109
|
end
|
98
|
-
end
|
110
|
+
end.compact
|
111
|
+
|
112
|
+
next if value.empty?
|
113
|
+
value << CSS_IMPORTANT if node[:important]
|
114
|
+
propstring = format("%s:%s", name, value.join(" "))
|
115
|
+
sanitized_node = Crass.parse_properties(propstring).first
|
116
|
+
sanitized_tree << sanitized_node << CRASS_SEMICOLON
|
99
117
|
end
|
100
118
|
|
101
|
-
Crass::Parser.stringify
|
119
|
+
Crass::Parser.stringify(sanitized_tree)
|
102
120
|
end
|
103
121
|
|
104
122
|
#
|
@@ -106,7 +124,7 @@ module Loofah
|
|
106
124
|
#
|
107
125
|
# see comments about CVE-2018-8048 within the tests for more information
|
108
126
|
#
|
109
|
-
def force_correct_attribute_escaping!
|
127
|
+
def force_correct_attribute_escaping!(node)
|
110
128
|
return unless Nokogiri::VersionInfo.instance.libxml2?
|
111
129
|
|
112
130
|
node.attribute_nodes.each do |attr_node|
|
@@ -122,11 +140,10 @@ module Loofah
|
|
122
140
|
#
|
123
141
|
encoding = attr_node.value.encoding
|
124
142
|
attr_node.value = attr_node.value.gsub(/[ "]/) do |m|
|
125
|
-
|
143
|
+
"%" + m.unpack("H2" * m.bytesize).join("%").upcase
|
126
144
|
end.force_encoding(encoding)
|
127
145
|
end
|
128
146
|
end
|
129
|
-
|
130
147
|
end
|
131
148
|
end
|
132
149
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Loofah
|
2
3
|
#
|
3
4
|
# Mixes +scrub!+ into Document, DocumentFragment, Node and NodeSet.
|
@@ -91,7 +92,7 @@ module Loofah
|
|
91
92
|
# # decidedly not ok for browser:
|
92
93
|
# frag.text(:encode_special_chars => false) # => "<script>alert('EVIL');</script>"
|
93
94
|
#
|
94
|
-
def text(options={})
|
95
|
+
def text(options = {})
|
95
96
|
result = serialize_root.children.inner_text rescue ""
|
96
97
|
if options[:encode_special_chars] == false
|
97
98
|
result # possibly dangerous if rendered in a browser
|
@@ -99,8 +100,9 @@ module Loofah
|
|
99
100
|
encode_special_chars result
|
100
101
|
end
|
101
102
|
end
|
103
|
+
|
102
104
|
alias :inner_text :text
|
103
|
-
alias :to_str
|
105
|
+
alias :to_str :text
|
104
106
|
|
105
107
|
#
|
106
108
|
# Returns a plain-text version of the markup contained by the
|
@@ -112,7 +114,7 @@ module Loofah
|
|
112
114
|
# Loofah.document("<h1>Title</h1><div>Content</div>").to_text
|
113
115
|
# # => "\nTitle\n\nContent\n"
|
114
116
|
#
|
115
|
-
def to_text(options={})
|
117
|
+
def to_text(options = {})
|
116
118
|
Loofah.remove_extraneous_whitespace self.dup.scrub!(:newline_block_elements).text(options)
|
117
119
|
end
|
118
120
|
end
|
data/lib/loofah/metahelpers.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Loofah
|
2
3
|
module MetaHelpers # :nodoc:
|
3
|
-
def self.add_downcased_set_members_to_all_set_constants
|
4
|
+
def self.add_downcased_set_members_to_all_set_constants(mojule)
|
4
5
|
mojule.constants.each do |constant_sym|
|
5
6
|
constant = mojule.const_get constant_sym
|
6
7
|
next unless Set === constant
|
data/lib/loofah/scrubber.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Loofah
|
2
3
|
#
|
3
4
|
# A RuntimeError raised when Loofah could not find an appropriate scrubber.
|
4
5
|
#
|
5
|
-
class ScrubberNotFound < RuntimeError
|
6
|
+
class ScrubberNotFound < RuntimeError; end
|
6
7
|
|
7
8
|
#
|
8
9
|
# A Scrubber wraps up a block (or method) that is run on an HTML node (element):
|
@@ -36,7 +37,7 @@ module Loofah
|
|
36
37
|
CONTINUE = Object.new.freeze
|
37
38
|
|
38
39
|
# Top-down Scrubbers may return STOP to indicate that the subtree should not be traversed.
|
39
|
-
STOP
|
40
|
+
STOP = Object.new.freeze
|
40
41
|
|
41
42
|
# When a scrubber is initialized, the :direction may be specified
|
42
43
|
# as :top_down (the default) or :bottom_up.
|
@@ -64,7 +65,7 @@ module Loofah
|
|
64
65
|
def initialize(options = {}, &block)
|
65
66
|
direction = options[:direction] || :top_down
|
66
67
|
unless [:top_down, :bottom_up].include?(direction)
|
67
|
-
raise ArgumentError, "direction #{direction} must be one of :top_down or :bottom_up"
|
68
|
+
raise ArgumentError, "direction #{direction} must be one of :top_down or :bottom_up"
|
68
69
|
end
|
69
70
|
@direction, @block = direction, block
|
70
71
|
end
|
@@ -91,10 +92,10 @@ module Loofah
|
|
91
92
|
# If the attribute is set, don't overwrite the existing value
|
92
93
|
#
|
93
94
|
def append_attribute(node, attribute, value)
|
94
|
-
current_value = node.get_attribute(attribute) ||
|
95
|
+
current_value = node.get_attribute(attribute) || ""
|
95
96
|
current_values = current_value.split(/\s+/)
|
96
97
|
updated_value = current_values | [value]
|
97
|
-
node.set_attribute(attribute, updated_value.join(
|
98
|
+
node.set_attribute(attribute, updated_value.join(" "))
|
98
99
|
end
|
99
100
|
|
100
101
|
private
|
@@ -118,11 +119,11 @@ module Loofah
|
|
118
119
|
else
|
119
120
|
return if scrub(node) == STOP
|
120
121
|
end
|
121
|
-
node.children.each {|j| traverse_conditionally_top_down(j)}
|
122
|
+
node.children.each { |j| traverse_conditionally_top_down(j) }
|
122
123
|
end
|
123
124
|
|
124
125
|
def traverse_conditionally_bottom_up(node)
|
125
|
-
node.children.each {|j| traverse_conditionally_bottom_up(j)}
|
126
|
+
node.children.each { |j| traverse_conditionally_bottom_up(j) }
|
126
127
|
if block
|
127
128
|
block.call(node)
|
128
129
|
else
|
data/lib/loofah/scrubbers.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Loofah
|
2
3
|
#
|
3
4
|
# Loofah provides some built-in scrubbers for sanitizing with
|
4
|
-
# HTML5lib's
|
5
|
+
# HTML5lib's safelist and for accomplishing some common
|
5
6
|
# transformation tasks.
|
6
7
|
#
|
7
8
|
#
|
@@ -205,8 +206,8 @@ module Loofah
|
|
205
206
|
end
|
206
207
|
|
207
208
|
def scrub(node)
|
208
|
-
return CONTINUE unless (node.type == Nokogiri::XML::Node::ELEMENT_NODE) && (node.name ==
|
209
|
-
append_attribute(node,
|
209
|
+
return CONTINUE unless (node.type == Nokogiri::XML::Node::ELEMENT_NODE) && (node.name == "a")
|
210
|
+
append_attribute(node, "rel", "nofollow")
|
210
211
|
return STOP
|
211
212
|
end
|
212
213
|
end
|
@@ -226,8 +227,8 @@ module Loofah
|
|
226
227
|
end
|
227
228
|
|
228
229
|
def scrub(node)
|
229
|
-
return CONTINUE unless (node.type == Nokogiri::XML::Node::ELEMENT_NODE) && (node.name ==
|
230
|
-
append_attribute(node,
|
230
|
+
return CONTINUE unless (node.type == Nokogiri::XML::Node::ELEMENT_NODE) && (node.name == "a")
|
231
|
+
append_attribute(node, "rel", "noopener")
|
231
232
|
return STOP
|
232
233
|
end
|
233
234
|
end
|
@@ -267,7 +268,7 @@ module Loofah
|
|
267
268
|
|
268
269
|
def scrub(node)
|
269
270
|
if node.type == Nokogiri::XML::Node::TEXT_NODE || node.type == Nokogiri::XML::Node::CDATA_SECTION_NODE
|
270
|
-
node.content = node.content.gsub(/\u2028|\u2029/,
|
271
|
+
node.content = node.content.gsub(/\u2028|\u2029/, "")
|
271
272
|
end
|
272
273
|
CONTINUE
|
273
274
|
end
|
@@ -277,14 +278,14 @@ module Loofah
|
|
277
278
|
# A hash that maps a symbol (like +:prune+) to the appropriate Scrubber (Loofah::Scrubbers::Prune).
|
278
279
|
#
|
279
280
|
MAP = {
|
280
|
-
:escape
|
281
|
-
:prune
|
281
|
+
:escape => Escape,
|
282
|
+
:prune => Prune,
|
282
283
|
:whitewash => Whitewash,
|
283
|
-
:strip
|
284
|
-
:nofollow
|
284
|
+
:strip => Strip,
|
285
|
+
:nofollow => NoFollow,
|
285
286
|
:noopener => NoOpener,
|
286
287
|
:newline_block_elements => NewlineBlockElements,
|
287
|
-
:unprintable => Unprintable
|
288
|
+
:unprintable => Unprintable,
|
288
289
|
}
|
289
290
|
|
290
291
|
#
|
data/lib/loofah/xml/document.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Loofah
|
2
3
|
module XML # :nodoc:
|
3
4
|
#
|
@@ -12,7 +13,7 @@ module Loofah
|
|
12
13
|
# constructor. Applications should use Loofah.fragment to
|
13
14
|
# parse a fragment.
|
14
15
|
#
|
15
|
-
def parse
|
16
|
+
def parse(tags)
|
16
17
|
doc = Loofah::XML::Document.new
|
17
18
|
doc.encoding = tags.encoding.name if tags.respond_to?(:encoding)
|
18
19
|
self.new(doc, tags)
|
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.
|
4
|
+
version: 2.9.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:
|
12
|
+
date: 2021-01-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nokogiri
|
@@ -43,30 +43,30 @@ dependencies:
|
|
43
43
|
name: rake
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- - "
|
46
|
+
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: '0
|
48
|
+
version: '13.0'
|
49
49
|
type: :development
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
|
-
- - "
|
53
|
+
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: '0
|
55
|
+
version: '13.0'
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: minitest
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
60
|
- - "~>"
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version: '
|
62
|
+
version: '5.14'
|
63
63
|
type: :development
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
67
|
- - "~>"
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: '
|
69
|
+
version: '5.14'
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: rr
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
@@ -85,86 +85,44 @@ dependencies:
|
|
85
85
|
name: json
|
86
86
|
requirement: !ruby/object:Gem::Requirement
|
87
87
|
requirements:
|
88
|
-
- - "
|
89
|
-
- !ruby/object:Gem::Version
|
90
|
-
version: '0'
|
91
|
-
type: :development
|
92
|
-
prerelease: false
|
93
|
-
version_requirements: !ruby/object:Gem::Requirement
|
94
|
-
requirements:
|
95
|
-
- - ">="
|
96
|
-
- !ruby/object:Gem::Version
|
97
|
-
version: '0'
|
98
|
-
- !ruby/object:Gem::Dependency
|
99
|
-
name: hoe-gemspec
|
100
|
-
requirement: !ruby/object:Gem::Requirement
|
101
|
-
requirements:
|
102
|
-
- - ">="
|
103
|
-
- !ruby/object:Gem::Version
|
104
|
-
version: '0'
|
105
|
-
type: :development
|
106
|
-
prerelease: false
|
107
|
-
version_requirements: !ruby/object:Gem::Requirement
|
108
|
-
requirements:
|
109
|
-
- - ">="
|
110
|
-
- !ruby/object:Gem::Version
|
111
|
-
version: '0'
|
112
|
-
- !ruby/object:Gem::Dependency
|
113
|
-
name: hoe-debugging
|
114
|
-
requirement: !ruby/object:Gem::Requirement
|
115
|
-
requirements:
|
116
|
-
- - ">="
|
117
|
-
- !ruby/object:Gem::Version
|
118
|
-
version: '0'
|
119
|
-
type: :development
|
120
|
-
prerelease: false
|
121
|
-
version_requirements: !ruby/object:Gem::Requirement
|
122
|
-
requirements:
|
123
|
-
- - ">="
|
124
|
-
- !ruby/object:Gem::Version
|
125
|
-
version: '0'
|
126
|
-
- !ruby/object:Gem::Dependency
|
127
|
-
name: hoe-bundler
|
128
|
-
requirement: !ruby/object:Gem::Requirement
|
129
|
-
requirements:
|
130
|
-
- - ">="
|
88
|
+
- - "~>"
|
131
89
|
- !ruby/object:Gem::Version
|
132
|
-
version: '
|
90
|
+
version: '2.2'
|
133
91
|
type: :development
|
134
92
|
prerelease: false
|
135
93
|
version_requirements: !ruby/object:Gem::Requirement
|
136
94
|
requirements:
|
137
|
-
- - "
|
95
|
+
- - "~>"
|
138
96
|
- !ruby/object:Gem::Version
|
139
|
-
version: '
|
97
|
+
version: '2.2'
|
140
98
|
- !ruby/object:Gem::Dependency
|
141
|
-
name:
|
99
|
+
name: concourse
|
142
100
|
requirement: !ruby/object:Gem::Requirement
|
143
101
|
requirements:
|
144
|
-
- - "
|
102
|
+
- - "~>"
|
145
103
|
- !ruby/object:Gem::Version
|
146
|
-
version: '0'
|
104
|
+
version: '0.33'
|
147
105
|
type: :development
|
148
106
|
prerelease: false
|
149
107
|
version_requirements: !ruby/object:Gem::Requirement
|
150
108
|
requirements:
|
151
|
-
- - "
|
109
|
+
- - "~>"
|
152
110
|
- !ruby/object:Gem::Version
|
153
|
-
version: '0'
|
111
|
+
version: '0.33'
|
154
112
|
- !ruby/object:Gem::Dependency
|
155
|
-
name:
|
113
|
+
name: rubocop
|
156
114
|
requirement: !ruby/object:Gem::Requirement
|
157
115
|
requirements:
|
158
|
-
- - "
|
116
|
+
- - "~>"
|
159
117
|
- !ruby/object:Gem::Version
|
160
|
-
version:
|
118
|
+
version: '1.1'
|
161
119
|
type: :development
|
162
120
|
prerelease: false
|
163
121
|
version_requirements: !ruby/object:Gem::Requirement
|
164
122
|
requirements:
|
165
|
-
- - "
|
123
|
+
- - "~>"
|
166
124
|
- !ruby/object:Gem::Version
|
167
|
-
version:
|
125
|
+
version: '1.1'
|
168
126
|
- !ruby/object:Gem::Dependency
|
169
127
|
name: rdoc
|
170
128
|
requirement: !ruby/object:Gem::Requirement
|
@@ -186,91 +144,62 @@ dependencies:
|
|
186
144
|
- !ruby/object:Gem::Version
|
187
145
|
version: '7'
|
188
146
|
- !ruby/object:Gem::Dependency
|
189
|
-
name: hoe
|
147
|
+
name: hoe-markdown
|
190
148
|
requirement: !ruby/object:Gem::Requirement
|
191
149
|
requirements:
|
192
150
|
- - "~>"
|
193
151
|
- !ruby/object:Gem::Version
|
194
|
-
version: '3
|
152
|
+
version: '1.3'
|
195
153
|
type: :development
|
196
154
|
prerelease: false
|
197
155
|
version_requirements: !ruby/object:Gem::Requirement
|
198
156
|
requirements:
|
199
157
|
- - "~>"
|
200
158
|
- !ruby/object:Gem::Version
|
201
|
-
version: '3
|
159
|
+
version: '1.3'
|
202
160
|
description: |-
|
203
|
-
Loofah is a general library for manipulating and transforming HTML/XML
|
204
|
-
documents and fragments. It's built on top of Nokogiri and libxml2, so
|
205
|
-
it's fast and has a nice API.
|
161
|
+
Loofah is a general library for manipulating and transforming HTML/XML documents and fragments, built on top of Nokogiri.
|
206
162
|
|
207
|
-
Loofah excels at HTML sanitization (XSS prevention). It includes some
|
208
|
-
nice HTML sanitizers, which are based on HTML5lib's whitelist, so it
|
209
|
-
most likely won't make your codes less secure. (These statements have
|
210
|
-
not been evaluated by Netexperts.)
|
163
|
+
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.)
|
211
164
|
|
212
|
-
ActiveRecord extensions for sanitization are available in the
|
213
|
-
[`loofah-activerecord` gem](https://github.com/flavorjones/loofah-activerecord).
|
165
|
+
ActiveRecord extensions for sanitization are available in the [`loofah-activerecord` gem](https://github.com/flavorjones/loofah-activerecord).
|
214
166
|
email:
|
215
167
|
- mike.dalessio@gmail.com
|
216
168
|
- bryan@brynary.com
|
217
169
|
executables: []
|
218
170
|
extensions: []
|
219
|
-
extra_rdoc_files:
|
220
|
-
- CHANGELOG.md
|
221
|
-
- MIT-LICENSE.txt
|
222
|
-
- Manifest.txt
|
223
|
-
- README.md
|
224
|
-
- SECURITY.md
|
171
|
+
extra_rdoc_files: []
|
225
172
|
files:
|
226
|
-
- ".gemtest"
|
227
173
|
- CHANGELOG.md
|
228
|
-
- Gemfile
|
229
174
|
- MIT-LICENSE.txt
|
230
|
-
- Manifest.txt
|
231
175
|
- README.md
|
232
|
-
- Rakefile
|
233
176
|
- SECURITY.md
|
234
|
-
- benchmark/benchmark.rb
|
235
|
-
- benchmark/fragment.html
|
236
|
-
- benchmark/helper.rb
|
237
|
-
- benchmark/www.slashdot.com.html
|
238
177
|
- lib/loofah.rb
|
239
178
|
- lib/loofah/elements.rb
|
240
179
|
- lib/loofah/helpers.rb
|
241
180
|
- lib/loofah/html/document.rb
|
242
181
|
- lib/loofah/html/document_fragment.rb
|
243
182
|
- lib/loofah/html5/libxml2_workarounds.rb
|
183
|
+
- lib/loofah/html5/safelist.rb
|
244
184
|
- lib/loofah/html5/scrub.rb
|
245
|
-
- lib/loofah/html5/whitelist.rb
|
246
185
|
- lib/loofah/instance_methods.rb
|
247
186
|
- lib/loofah/metahelpers.rb
|
248
187
|
- lib/loofah/scrubber.rb
|
249
188
|
- lib/loofah/scrubbers.rb
|
189
|
+
- lib/loofah/version.rb
|
250
190
|
- lib/loofah/xml/document.rb
|
251
191
|
- lib/loofah/xml/document_fragment.rb
|
252
|
-
- test/assets/msword.html
|
253
|
-
- test/assets/testdata_sanitizer_tests1.dat
|
254
|
-
- test/helper.rb
|
255
|
-
- test/html5/test_sanitizer.rb
|
256
|
-
- test/integration/test_ad_hoc.rb
|
257
|
-
- test/integration/test_helpers.rb
|
258
|
-
- test/integration/test_html.rb
|
259
|
-
- test/integration/test_scrubbers.rb
|
260
|
-
- test/integration/test_xml.rb
|
261
|
-
- test/unit/test_api.rb
|
262
|
-
- test/unit/test_encoding.rb
|
263
|
-
- test/unit/test_helpers.rb
|
264
|
-
- test/unit/test_scrubber.rb
|
265
|
-
- test/unit/test_scrubbers.rb
|
266
192
|
homepage: https://github.com/flavorjones/loofah
|
267
193
|
licenses:
|
268
194
|
- MIT
|
269
|
-
metadata:
|
195
|
+
metadata:
|
196
|
+
homepage_uri: https://github.com/flavorjones/loofah
|
197
|
+
source_code_uri: https://github.com/flavorjones/loofah
|
198
|
+
bug_tracker_uri: https://github.com/flavorjones/loofah/issues
|
199
|
+
changelog_uri: https://github.com/flavorjones/loofah/blob/master/CHANGELOG.md
|
200
|
+
documentation_uri: https://www.rubydoc.info/gems/loofah/
|
270
201
|
post_install_message:
|
271
|
-
rdoc_options:
|
272
|
-
- "--main"
|
273
|
-
- README.md
|
202
|
+
rdoc_options: []
|
274
203
|
require_paths:
|
275
204
|
- lib
|
276
205
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -284,10 +213,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
284
213
|
- !ruby/object:Gem::Version
|
285
214
|
version: '0'
|
286
215
|
requirements: []
|
287
|
-
|
288
|
-
rubygems_version: 2.7.7
|
216
|
+
rubygems_version: 3.1.4
|
289
217
|
signing_key:
|
290
218
|
specification_version: 4
|
291
219
|
summary: Loofah is a general library for manipulating and transforming HTML/XML documents
|
292
|
-
and fragments
|
220
|
+
and fragments, built on top of Nokogiri
|
293
221
|
test_files: []
|