loofah 2.3.0 → 2.7.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.

@@ -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 :text
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
@@ -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 mojule
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
@@ -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 ; end
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 = Object.new.freeze
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
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Loofah
2
3
  #
3
4
  # Loofah provides some built-in scrubbers for sanitizing with
@@ -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 == 'a')
209
- append_attribute(node, 'rel', 'nofollow')
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 == 'a')
230
- append_attribute(node, 'rel', 'noopener')
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 => Escape,
281
- :prune => Prune,
281
+ :escape => Escape,
282
+ :prune => Prune,
282
283
  :whitewash => Whitewash,
283
- :strip => Strip,
284
- :nofollow => 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
  #
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Loofah
2
3
  module XML # :nodoc:
3
4
  #
@@ -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 tags
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.3.0
4
+ version: 2.7.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: 2019-09-28 00:00:00.000000000 Z
12
+ date: 2020-08-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
@@ -87,14 +87,14 @@ dependencies:
87
87
  requirements:
88
88
  - - "~>"
89
89
  - !ruby/object:Gem::Version
90
- version: 2.2.0
90
+ version: 2.3.0
91
91
  type: :development
92
92
  prerelease: false
93
93
  version_requirements: !ruby/object:Gem::Requirement
94
94
  requirements:
95
95
  - - "~>"
96
96
  - !ruby/object:Gem::Version
97
- version: 2.2.0
97
+ version: 2.3.0
98
98
  - !ruby/object:Gem::Dependency
99
99
  name: hoe-gemspec
100
100
  requirement: !ruby/object:Gem::Requirement
@@ -151,6 +151,20 @@ dependencies:
151
151
  - - "~>"
152
152
  - !ruby/object:Gem::Version
153
153
  version: '1.6'
154
+ - !ruby/object:Gem::Dependency
155
+ name: hoe-markdown
156
+ requirement: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - "~>"
159
+ - !ruby/object:Gem::Version
160
+ version: '1.2'
161
+ type: :development
162
+ prerelease: false
163
+ version_requirements: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - "~>"
166
+ - !ruby/object:Gem::Version
167
+ version: '1.2'
154
168
  - !ruby/object:Gem::Dependency
155
169
  name: concourse
156
170
  requirement: !ruby/object:Gem::Requirement
@@ -165,6 +179,20 @@ dependencies:
165
179
  - - ">="
166
180
  - !ruby/object:Gem::Version
167
181
  version: 0.26.0
182
+ - !ruby/object:Gem::Dependency
183
+ name: rubocop
184
+ requirement: !ruby/object:Gem::Requirement
185
+ requirements:
186
+ - - ">="
187
+ - !ruby/object:Gem::Version
188
+ version: 0.76.0
189
+ type: :development
190
+ prerelease: false
191
+ version_requirements: !ruby/object:Gem::Requirement
192
+ requirements:
193
+ - - ">="
194
+ - !ruby/object:Gem::Version
195
+ version: 0.76.0
168
196
  - !ruby/object:Gem::Dependency
169
197
  name: rdoc
170
198
  requirement: !ruby/object:Gem::Requirement
@@ -191,26 +219,20 @@ dependencies:
191
219
  requirements:
192
220
  - - "~>"
193
221
  - !ruby/object:Gem::Version
194
- version: '3.18'
222
+ version: '3.22'
195
223
  type: :development
196
224
  prerelease: false
197
225
  version_requirements: !ruby/object:Gem::Requirement
198
226
  requirements:
199
227
  - - "~>"
200
228
  - !ruby/object:Gem::Version
201
- version: '3.18'
229
+ version: '3.22'
202
230
  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.
231
+ Loofah is a general library for manipulating and transforming HTML/XML documents and fragments, built on top of Nokogiri.
206
232
 
207
- Loofah excels at HTML sanitization (XSS prevention). It includes some
208
- nice HTML sanitizers, which are based on HTML5lib's safelist, so it
209
- most likely won't make your codes less secure. (These statements have
210
- not been evaluated by Netexperts.)
233
+ 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
234
 
212
- ActiveRecord extensions for sanitization are available in the
213
- [`loofah-activerecord` gem](https://github.com/flavorjones/loofah-activerecord).
235
+ ActiveRecord extensions for sanitization are available in the [`loofah-activerecord` gem](https://github.com/flavorjones/loofah-activerecord).
214
236
  email:
215
237
  - mike.dalessio@gmail.com
216
238
  - bryan@brynary.com
@@ -223,7 +245,6 @@ extra_rdoc_files:
223
245
  - README.md
224
246
  - SECURITY.md
225
247
  files:
226
- - ".gemtest"
227
248
  - CHANGELOG.md
228
249
  - Gemfile
229
250
  - MIT-LICENSE.txt
@@ -249,25 +270,15 @@ files:
249
270
  - lib/loofah/scrubbers.rb
250
271
  - lib/loofah/xml/document.rb
251
272
  - 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/html5/test_scrub.rb
257
- - test/integration/test_ad_hoc.rb
258
- - test/integration/test_helpers.rb
259
- - test/integration/test_html.rb
260
- - test/integration/test_scrubbers.rb
261
- - test/integration/test_xml.rb
262
- - test/unit/test_api.rb
263
- - test/unit/test_encoding.rb
264
- - test/unit/test_helpers.rb
265
- - test/unit/test_scrubber.rb
266
- - test/unit/test_scrubbers.rb
267
273
  homepage: https://github.com/flavorjones/loofah
268
274
  licenses:
269
275
  - MIT
270
- metadata: {}
276
+ metadata:
277
+ homepage_uri: https://github.com/flavorjones/loofah
278
+ bug_tracker_uri: https://github.com/flavorjones/loofah/issues
279
+ documentation_uri: https://www.rubydoc.info/gems/loofah/
280
+ changelog_uri: https://github.com/flavorjones/loofah/blob/master/CHANGELOG.md
281
+ source_code_uri: https://github.com/flavorjones/loofah
271
282
  post_install_message:
272
283
  rdoc_options:
273
284
  - "--main"
@@ -285,9 +296,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
285
296
  - !ruby/object:Gem::Version
286
297
  version: '0'
287
298
  requirements: []
288
- rubygems_version: 3.0.3
299
+ rubygems_version: 3.1.2
289
300
  signing_key:
290
301
  specification_version: 4
291
302
  summary: Loofah is a general library for manipulating and transforming HTML/XML documents
292
- and fragments
303
+ and fragments, built on top of Nokogiri
293
304
  test_files: []
data/.gemtest DELETED
File without changes
@@ -1,63 +0,0 @@
1
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="ProgId" content="Word.Document"><meta name="Generator" content="Microsoft Word 11"><meta name="Originator" content="Microsoft Word 11"><link rel="File-List" href="file:///C:%5CDOCUME%7E1%5CNICOLE%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_filelist.xml"><!--[if gte mso 9]><xml>
2
- <w:WordDocument>
3
- <w:View>Normal</w:View>
4
- <w:Zoom>0</w:Zoom>
5
- <w:PunctuationKerning/>
6
- <w:ValidateAgainstSchemas/>
7
- <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
8
- <w:IgnoreMixedContent>false</w:IgnoreMixedContent>
9
- <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
10
- <w:Compatibility>
11
- <w:BreakWrappedTables/>
12
- <w:SnapToGridInCell/>
13
- <w:WrapTextWithPunct/>
14
- <w:UseAsianBreakRules/>
15
- <w:DontGrowAutofit/>
16
- </w:Compatibility>
17
- <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
18
- </w:WordDocument>
19
- </xml><![endif]--><!--[if gte mso 9]><xml>
20
- <w:LatentStyles DefLockedState="false" LatentStyleCount="156">
21
- </w:LatentStyles>
22
- </xml><![endif]--><style>
23
- <!--
24
- /* Style Definitions */
25
- p.MsoNormal, li.MsoNormal, div.MsoNormal
26
- {mso-style-parent:"";
27
- margin:0in;
28
- margin-bottom:.0001pt;
29
- mso-pagination:widow-orphan;
30
- font-size:12.0pt;
31
- font-family:"Times New Roman";
32
- mso-fareast-font-family:"Times New Roman";}
33
- @page Section1
34
- {size:8.5in 11.0in;
35
- margin:1.0in 1.25in 1.0in 1.25in;
36
- mso-header-margin:.5in;
37
- mso-footer-margin:.5in;
38
- mso-paper-source:0;}
39
- div.Section1
40
- {page:Section1;}
41
- -->
42
- </style><!--[if gte mso 10]>
43
- <style>
44
- /* Style Definitions */
45
- table.MsoNormalTable
46
- {mso-style-name:"Table Normal";
47
- mso-tstyle-rowband-size:0;
48
- mso-tstyle-colband-size:0;
49
- mso-style-noshow:yes;
50
- mso-style-parent:"";
51
- mso-padding-alt:0in 5.4pt 0in 5.4pt;
52
- mso-para-margin:0in;
53
- mso-para-margin-bottom:.0001pt;
54
- mso-pagination:widow-orphan;
55
- font-size:10.0pt;
56
- font-family:"Times New Roman";
57
- mso-ansi-language:#0400;
58
- mso-fareast-language:#0400;
59
- mso-bidi-language:#0400;}
60
- </style>
61
- <![endif]-->
62
-
63
- <p class="MsoNormal">Foo <b style="">BOLD<o:p></o:p></b></p>
@@ -1,502 +0,0 @@
1
- [
2
- {
3
- "name": "IE_Comments",
4
- "input": "<!--[if gte IE 4]><script>alert('XSS');</script><![endif]-->",
5
- "output": "&lt;!--[if gte IE 4]&gt;&lt;script&gt;alert('XSS');&lt;/script&gt;&lt;![endif]--&gt;"
6
- },
7
-
8
- {
9
- "name": "IE_Comments_2",
10
- "input": "<![if !IE 5]><script>alert('XSS');</script><![endif]>",
11
- "output": "&lt;script&gt;alert('XSS');&lt;/script&gt;",
12
- "rexml": "Ill-formed XHTML!"
13
- },
14
-
15
- {
16
- "name": "allow_colons_in_path_component",
17
- "input": "<a href=\"./this:that\">foo</a>",
18
- "output": "<a href='./this:that'>foo</a>"
19
- },
20
-
21
- {
22
- "name": "background_attribute",
23
- "input": "<div background=\"javascript:alert('XSS')\"></div>",
24
- "output": "<div/>",
25
- "xhtml": "<div></div>",
26
- "rexml": "<div></div>"
27
- },
28
-
29
- {
30
- "name": "bgsound",
31
- "input": "<bgsound src=\"javascript:alert('XSS');\" />",
32
- "output": "&lt;bgsound src=\"javascript:alert('XSS');\"/&gt;",
33
- "rexml": "&lt;bgsound src=\"javascript:alert('XSS');\"&gt;&lt;/bgsound&gt;"
34
- },
35
-
36
- {
37
- "name": "div_background_image_unicode_encoded",
38
- "input": "<div style=\"background-image:\u00a5\u00a2\u006C\u0028'\u006a\u0061\u00a6\u0061\u00a3\u0063\u00a2\u0069\u00a0\u00a4\u003a\u0061\u006c\u0065\u00a2\u00a4\u0028.1027\u0058.1053\u0053\u0027\u0029'\u0029\">foo</div>",
39
- "output": "<div>foo</div>"
40
- },
41
-
42
- {
43
- "name": "div_expression",
44
- "input": "<div style=\"width: expression(alert('XSS'));\">foo</div>",
45
- "output": "<div>foo</div>"
46
- },
47
-
48
- {
49
- "name": "double_open_angle_brackets",
50
- "input": "<img src=http://ha.ckers.org/scriptlet.html <",
51
- "output": "<img src='http://ha.ckers.org/scriptlet.html'>",
52
- "rexml": "Ill-formed XHTML!"
53
- },
54
-
55
- {
56
- "name": "double_open_angle_brackets_2",
57
- "input": "<script src=http://ha.ckers.org/scriptlet.html <",
58
- "output": "&lt;script src=\"http://ha.ckers.org/scriptlet.html\"&gt;&lt;/script&gt;",
59
- "rexml": "Ill-formed XHTML!"
60
- },
61
-
62
- {
63
- "name": "grave_accents",
64
- "input": "<img src=`javascript:alert('XSS')` />",
65
- "output": "<img>",
66
- "rexml": "Ill-formed XHTML!"
67
- },
68
-
69
- {
70
- "name": "img_dynsrc_lowsrc",
71
- "input": "<img dynsrc=\"javascript:alert('XSS')\" />",
72
- "output": "<img>",
73
- "rexml": "<img />"
74
- },
75
-
76
- {
77
- "name": "img_vbscript",
78
- "input": "<img src='vbscript:msgbox(\"XSS\")' />",
79
- "output": "<img>",
80
- "rexml": "<img />"
81
- },
82
-
83
- {
84
- "name": "input_image",
85
- "input": "<input type=\"image\" src=\"javascript:alert('XSS');\" />",
86
- "output": "<input type='image'>",
87
- "rexml": "<input type='image' />"
88
- },
89
-
90
- {
91
- "name": "link_stylesheets",
92
- "input": "<link rel=\"stylesheet\" href=\"javascript:alert('XSS');\" />",
93
- "output": "&lt;link rel=\"stylesheet\" href=\"javascript:alert('XSS');\"&gt;",
94
- "rexml": "&lt;link href=\"javascript:alert('XSS');\" rel=\"stylesheet\"/&gt;"
95
- },
96
-
97
- {
98
- "name": "link_stylesheets_2",
99
- "input": "<link rel=\"stylesheet\" href=\"http://ha.ckers.org/xss.css\" />",
100
- "output": "&lt;link rel=\"stylesheet\" href=\"http://ha.ckers.org/xss.css\"&gt;",
101
- "rexml": "&lt;link href=\"http://ha.ckers.org/xss.css\" rel=\"stylesheet\"/&gt;"
102
- },
103
-
104
- {
105
- "name": "list_style_image",
106
- "input": "<li style=\"list-style-image: url(javascript:alert('XSS'))\">foo</li>",
107
- "output": "<li>foo</li>"
108
- },
109
-
110
- {
111
- "name": "no_closing_script_tags",
112
- "input": "<script src=http://ha.ckers.org/xss.js?<b>",
113
- "output": "&lt;script src=\"http://ha.ckers.org/xss.js?&amp;lt;b\"&gt;&lt;/script&gt;",
114
- "rexml": "Ill-formed XHTML!"
115
- },
116
-
117
- {
118
- "name": "non_alpha_non_digit",
119
- "input": "<script/XSS src=\"http://ha.ckers.org/xss.js\"></script>",
120
- "output": "&lt;script src=\"http://ha.ckers.org/xss.js\"&gt;&lt;/script&gt;",
121
- "rexml": "Ill-formed XHTML!"
122
- },
123
-
124
- {
125
- "name": "non_alpha_non_digit_2",
126
- "input": "<a onclick!\\#$%&()*~+-_.,:;?@[/|\\]^`=alert(\"XSS\")>foo</a>",
127
- "output": "<a>foo</a>",
128
- "rexml": "Ill-formed XHTML!"
129
- },
130
-
131
- {
132
- "name": "non_alpha_non_digit_3",
133
- "input": "<img/src=\"http://ha.ckers.org/xss.js\"/>",
134
- "output": "<img>",
135
- "rexml": "Ill-formed XHTML!"
136
- },
137
-
138
- {
139
- "name": "non_alpha_non_digit_II",
140
- "input": "<a href!\\#$%&()*~+-_.,:;?@[/|]^`=alert('XSS')>foo</a>",
141
- "output": "<a>foo</a>",
142
- "rexml": "Ill-formed XHTML!"
143
- },
144
-
145
- {
146
- "name": "non_alpha_non_digit_III",
147
- "input": "<a/href=\"javascript:alert('XSS');\">foo</a>",
148
- "output": "<a>foo</a>",
149
- "rexml": "Ill-formed XHTML!"
150
- },
151
-
152
- {
153
- "name": "platypus",
154
- "input": "<a href=\"http://www.ragingplatypus.com/\" style=\"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;\">never trust your upstream platypus</a>",
155
- "output": "<a href='http://www.ragingplatypus.com/' style='display:block;width:100%;height:100%;background-color:black;background-x:center;background-y:center;'>never trust your upstream platypus</a>"
156
- },
157
-
158
- {
159
- "name": "protocol_resolution_in_script_tag",
160
- "input": "<script src=//ha.ckers.org/.j></script>",
161
- "output": "&lt;script src=\"//ha.ckers.org/.j\"&gt;&lt;/script&gt;",
162
- "rexml": "Ill-formed XHTML!"
163
- },
164
-
165
- {
166
- "name": "should_allow_anchors",
167
- "input": "<a href='foo' onclick='bar'><script>baz</script></a>",
168
- "output": "<a href='foo'>&lt;script&gt;baz&lt;/script&gt;</a>"
169
- },
170
-
171
- {
172
- "name": "should_allow_image_alt_attribute",
173
- "input": "<img alt='foo' onclick='bar' />",
174
- "output": "<img alt='foo'>",
175
- "rexml": "<img alt='foo' />"
176
- },
177
-
178
- {
179
- "name": "should_allow_image_height_attribute",
180
- "input": "<img height='foo' onclick='bar' />",
181
- "output": "<img height='foo'>",
182
- "rexml": "<img height='foo' />"
183
- },
184
-
185
- {
186
- "name": "should_allow_image_src_attribute",
187
- "input": "<img src='foo' onclick='bar' />",
188
- "output": "<img src='foo'>",
189
- "rexml": "<img src='foo' />"
190
- },
191
-
192
- {
193
- "name": "should_allow_image_width_attribute",
194
- "input": "<img width='foo' onclick='bar' />",
195
- "output": "<img width='foo'>",
196
- "rexml": "<img width='foo' />"
197
- },
198
-
199
- {
200
- "name": "should_handle_blank_text",
201
- "input": "",
202
- "output": ""
203
- },
204
-
205
- {
206
- "name": "should_handle_malformed_image_tags",
207
- "input": "<img \"\"\"><script>alert(\"XSS\")</script>\">",
208
- "output": "<img>&lt;script&gt;alert(\"XSS\")&lt;/script&gt;\"&gt;",
209
- "rexml": "Ill-formed XHTML!"
210
- },
211
-
212
- {
213
- "name": "should_handle_non_html",
214
- "input": "abc",
215
- "output": "abc"
216
- },
217
-
218
- {
219
- "name": "should_not_fall_for_ridiculous_hack",
220
- "input": "<img\nsrc\n=\n\"\nj\na\nv\na\ns\nc\nr\ni\np\nt\n:\na\nl\ne\nr\nt\n(\n'\nX\nS\nS\n'\n)\n\"\n />",
221
- "output": "<img>",
222
- "rexml": "<img />"
223
- },
224
-
225
- {
226
- "name": "should_not_fall_for_xss_image_hack_0",
227
- "input": "<img src=\"javascript:alert('XSS');\" />",
228
- "output": "<img>",
229
- "rexml": "<img />"
230
- },
231
-
232
- {
233
- "name": "should_not_fall_for_xss_image_hack_1",
234
- "input": "<img src=javascript:alert('XSS') />",
235
- "output": "<img>",
236
- "rexml": "Ill-formed XHTML!"
237
- },
238
-
239
- {
240
- "name": "should_not_fall_for_xss_image_hack_10",
241
- "input": "<img src=\"jav&#x0A;ascript:alert('XSS');\" />",
242
- "output": "<img>",
243
- "rexml": "<img />"
244
- },
245
-
246
- {
247
- "name": "should_not_fall_for_xss_image_hack_11",
248
- "input": "<img src=\"jav&#x0D;ascript:alert('XSS');\" />",
249
- "output": "<img>",
250
- "rexml": "<img />"
251
- },
252
-
253
- {
254
- "name": "should_not_fall_for_xss_image_hack_12",
255
- "input": "<img src=\" &#14; javascript:alert('XSS');\" />",
256
- "output": "<img>",
257
- "rexml": "<img />"
258
- },
259
-
260
- {
261
- "name": "should_not_fall_for_xss_image_hack_13",
262
- "input": "<img src=\"&#x20;javascript:alert('XSS');\" />",
263
- "output": "<img>",
264
- "rexml": "<img />"
265
- },
266
-
267
- {
268
- "name": "should_not_fall_for_xss_image_hack_14",
269
- "input": "<img src=\"&#xA0;javascript:alert('XSS');\" />",
270
- "output": "<img>",
271
- "rexml": "<img />"
272
- },
273
-
274
- {
275
- "name": "should_not_fall_for_xss_image_hack_2",
276
- "input": "<img src=\"JaVaScRiPt:alert('XSS')\" />",
277
- "output": "<img>",
278
- "rexml": "<img />"
279
- },
280
-
281
- {
282
- "name": "should_not_fall_for_xss_image_hack_3",
283
- "input": "<img src='javascript:alert(&quot;XSS&quot;)' />",
284
- "output": "<img>",
285
- "rexml": "<img />"
286
- },
287
-
288
- {
289
- "name": "should_not_fall_for_xss_image_hack_4",
290
- "input": "<img src='javascript:alert(String.fromCharCode(88,83,83))' />",
291
- "output": "<img>",
292
- "rexml": "<img />"
293
- },
294
-
295
- {
296
- "name": "should_not_fall_for_xss_image_hack_5",
297
- "input": "<img src='&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;' />",
298
- "output": "<img>",
299
- "rexml": "<img />"
300
- },
301
-
302
- {
303
- "name": "should_not_fall_for_xss_image_hack_6",
304
- "input": "<img src='&#0000106;&#0000097;&#0000118;&#0000097;&#0000115;&#0000099;&#0000114;&#0000105;&#0000112;&#0000116;&#0000058;&#0000097;&#0000108;&#0000101;&#0000114;&#0000116;&#0000040;&#0000039;&#0000088;&#0000083;&#0000083;&#0000039;&#0000041' />",
305
- "output": "<img>",
306
- "rexml": "<img />"
307
- },
308
-
309
- {
310
- "name": "should_not_fall_for_xss_image_hack_7",
311
- "input": "<img src='&#x6A;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3A;&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x27;&#x58;&#x53;&#x53;&#x27;&#x29' />",
312
- "output": "<img>",
313
- "rexml": "<img />"
314
- },
315
-
316
- {
317
- "name": "should_not_fall_for_xss_image_hack_8",
318
- "input": "<img src=\"jav\tascript:alert('XSS');\" />",
319
- "output": "<img>",
320
- "rexml": "<img />"
321
- },
322
-
323
- {
324
- "name": "should_not_fall_for_xss_image_hack_9",
325
- "input": "<img src=\"jav&#x09;ascript:alert('XSS');\" />",
326
- "output": "<img>",
327
- "rexml": "<img />"
328
- },
329
-
330
- {
331
- "name": "should_sanitize_half_open_scripts",
332
- "input": "<img src=\"javascript:alert('XSS')\"",
333
- "output": "<img>",
334
- "rexml": "Ill-formed XHTML!"
335
- },
336
-
337
- {
338
- "name": "should_sanitize_invalid_script_tag",
339
- "input": "<script/XSS SRC=\"http://ha.ckers.org/xss.js\"></script>",
340
- "output": "&lt;script src=\"http://ha.ckers.org/xss.js\"&gt;&lt;/script&gt;",
341
- "rexml": "Ill-formed XHTML!"
342
- },
343
-
344
- {
345
- "name": "should_sanitize_script_tag_with_multiple_open_brackets",
346
- "input": "<<script>alert(\"XSS\");//<</script>",
347
- "output": "alert(\"XSS\");//",
348
- "xhtml": "&lt;&lt;script&gt;alert('XSS');//&lt;&lt;/script&gt;",
349
- "rexml": "Ill-formed XHTML!"
350
- },
351
-
352
- {
353
- "name": "should_sanitize_script_tag_with_multiple_open_brackets_2",
354
- "input": "<iframe src=http://ha.ckers.org/scriptlet.html\n<",
355
- "output": "&lt;iframe src=\"http://ha.ckers.org/scriptlet.html\"&gt;&lt;/iframe&gt;",
356
- "rexml": "Ill-formed XHTML!"
357
- },
358
-
359
- {
360
- "name": "should_sanitize_tag_broken_up_by_null",
361
- "input": "<scr\u0000ipt>alert(\"XSS\")</scr\u0000ipt>",
362
- "output": "&lt;scr&gt;&lt;/scr&gt;",
363
- "rexml": "Ill-formed XHTML!"
364
- },
365
-
366
- {
367
- "name": "should_sanitize_unclosed_script",
368
- "input": "<script src=http://ha.ckers.org/xss.js?<b>",
369
- "output": "&lt;script src=\"http://ha.ckers.org/xss.js?&amp;lt;b\"&gt;&lt;/script&gt;",
370
- "rexml": "Ill-formed XHTML!"
371
- },
372
-
373
- {
374
- "name": "should_strip_href_attribute_in_a_with_bad_protocols",
375
- "input": "<a href=\"javascript:XSS\" title=\"1\">boo</a>",
376
- "output": "<a title='1'>boo</a>"
377
- },
378
-
379
- {
380
- "name": "should_strip_href_attribute_in_a_with_bad_protocols_and_whitespace",
381
- "input": "<a href=\" javascript:XSS\" title=\"1\">boo</a>",
382
- "output": "<a title='1'>boo</a>"
383
- },
384
-
385
- {
386
- "name": "should_strip_src_attribute_in_img_with_bad_protocols",
387
- "input": "<img src=\"javascript:XSS\" title=\"1\">boo</img>",
388
- "output": "<img title='1'>boo",
389
- "rexml": "<img title='1' />"
390
- },
391
-
392
- {
393
- "name": "should_strip_src_attribute_in_img_with_bad_protocols_and_whitespace",
394
- "input": "<img src=\" javascript:XSS\" title=\"1\">boo</img>",
395
- "output": "<img title='1'>boo",
396
- "rexml": "<img title='1' />"
397
- },
398
-
399
- {
400
- "name": "xml_base",
401
- "input": "<div xml:base=\"javascript:alert('XSS');//\">foo</div>",
402
- "output": "<div>foo</div>"
403
- },
404
-
405
- {
406
- "name": "xul",
407
- "input": "<p style=\"-moz-binding:url('http://ha.ckers.org/xssmoz.xml#xss')\">fubar</p>",
408
- "output": "<p>fubar</p>"
409
- },
410
-
411
- {
412
- "name": "quotes_in_attributes",
413
- "input": "<img src='foo' title='\"foo\" bar' />",
414
- "rexml": "<img src='foo' title='\"foo\" bar' />",
415
- "output": "<img src='foo' title='\"foo\" bar'>"
416
- },
417
-
418
- {
419
- "name": "uri_refs_in_svg_attributes",
420
- "input": "<rect fill='url(#foo)' />",
421
- "rexml": "<rect fill='url(#foo)'></rect>",
422
- "xhtml": "<rect fill='url(#foo)'></rect>",
423
- "output": "<rect fill='url(#foo)'/>"
424
- },
425
-
426
- {
427
- "name": "absolute_uri_refs_in_svg_attributes",
428
- "input": "<rect fill='url(http://bad.com/) #fff' />",
429
- "rexml": "<rect fill=' #fff'></rect>",
430
- "xhtml": "<rect fill=' #fff'></rect>",
431
- "output": "<rect fill=' #fff'/>"
432
- },
433
-
434
- {
435
- "name": "uri_ref_with_space_in svg_attribute",
436
- "input": "<rect fill='url(\n#foo)' />",
437
- "rexml": "<rect fill='url(\n#foo)'></rect>",
438
- "xhtml": "<rect fill='url(\n#foo)'></rect>",
439
- "output": "<rect fill='url(\n#foo)'/>"
440
- },
441
-
442
- {
443
- "name": "absolute_uri_ref_with_space_in svg_attribute",
444
- "input": "<rect fill=\"url(\nhttp://bad.com/)\" />",
445
- "rexml": "<rect></rect>",
446
- "xhtml": "<rect></rect>",
447
- "output": "<rect/>"
448
- },
449
-
450
- {
451
- "name": "allow_html5_image_tag",
452
- "input": "<image src='foo' />",
453
- "rexml": "&lt;image src=\"foo\"&gt;&lt;/image&gt;",
454
- "output": "&lt;image src=\"foo\"/&gt;"
455
- },
456
-
457
- {
458
- "name": "style_attr_end_with_nothing",
459
- "input": "<div style=\"color: blue\" />",
460
- "output": "<div style='color: blue;'/>",
461
- "xhtml": "<div style='color: blue;'></div>",
462
- "rexml": "<div style='color: blue;'></div>"
463
- },
464
-
465
- {
466
- "name": "style_attr_end_with_space",
467
- "input": "<div style=\"color: blue \" />",
468
- "output": "<div style='color: blue ;'/>",
469
- "xhtml": "<div style='color: blue ;'></div>",
470
- "rexml": "<div style='color: blue ;'></div>"
471
- },
472
-
473
- {
474
- "name": "style_attr_end_with_semicolon",
475
- "input": "<div style=\"color: blue;\" />",
476
- "output": "<div style='color: blue;'/>",
477
- "xhtml": "<div style='color: blue;'></div>",
478
- "rexml": "<div style='color: blue;'></div>"
479
- },
480
-
481
- {
482
- "name": "style_attr_end_with_semicolon_space",
483
- "input": "<div style=\"color: blue; \" />",
484
- "output": "<div style='color: blue;'/>",
485
- "xhtml": "<div style='color: blue;'></div>",
486
- "rexml": "<div style='color: blue;'></div>"
487
- },
488
-
489
- {
490
- "name": "attributes_with_embedded_quotes",
491
- "input": "<img src=doesntexist.jpg\"'onerror=\"alert(1) />",
492
- "output": "<img src='doesntexist.jpg%22'onerror=%22alert(1)'>",
493
- "rexml": "Ill-formed XHTML!"
494
- },
495
-
496
- {
497
- "name": "attributes_with_embedded_quotes_II",
498
- "input": "<img src=notthere.jpg\"\"onerror=\"alert(2) />",
499
- "output": "<img src='notthere.jpg%22%22onerror=%22alert(2)'>",
500
- "rexml": "Ill-formed XHTML!"
501
- }
502
- ]