loofah 2.3.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of loofah might be problematic. Click here for more details.

Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/.gemtest +0 -0
  3. data/CHANGELOG.md +336 -0
  4. data/Gemfile +22 -0
  5. data/MIT-LICENSE.txt +23 -0
  6. data/Manifest.txt +41 -0
  7. data/README.md +363 -0
  8. data/Rakefile +81 -0
  9. data/SECURITY.md +18 -0
  10. data/benchmark/benchmark.rb +149 -0
  11. data/benchmark/fragment.html +96 -0
  12. data/benchmark/helper.rb +73 -0
  13. data/benchmark/www.slashdot.com.html +2560 -0
  14. data/lib/loofah.rb +83 -0
  15. data/lib/loofah/elements.rb +92 -0
  16. data/lib/loofah/helpers.rb +103 -0
  17. data/lib/loofah/html/document.rb +18 -0
  18. data/lib/loofah/html/document_fragment.rb +40 -0
  19. data/lib/loofah/html5/libxml2_workarounds.rb +26 -0
  20. data/lib/loofah/html5/safelist.rb +796 -0
  21. data/lib/loofah/html5/scrub.rb +133 -0
  22. data/lib/loofah/instance_methods.rb +127 -0
  23. data/lib/loofah/metahelpers.rb +13 -0
  24. data/lib/loofah/scrubber.rb +133 -0
  25. data/lib/loofah/scrubbers.rb +297 -0
  26. data/lib/loofah/xml/document.rb +13 -0
  27. data/lib/loofah/xml/document_fragment.rb +23 -0
  28. data/test/assets/msword.html +63 -0
  29. data/test/assets/testdata_sanitizer_tests1.dat +502 -0
  30. data/test/helper.rb +18 -0
  31. data/test/html5/test_sanitizer.rb +401 -0
  32. data/test/html5/test_scrub.rb +10 -0
  33. data/test/integration/test_ad_hoc.rb +220 -0
  34. data/test/integration/test_helpers.rb +43 -0
  35. data/test/integration/test_html.rb +72 -0
  36. data/test/integration/test_scrubbers.rb +400 -0
  37. data/test/integration/test_xml.rb +55 -0
  38. data/test/unit/test_api.rb +142 -0
  39. data/test/unit/test_encoding.rb +20 -0
  40. data/test/unit/test_helpers.rb +62 -0
  41. data/test/unit/test_scrubber.rb +229 -0
  42. data/test/unit/test_scrubbers.rb +14 -0
  43. metadata +287 -0
@@ -0,0 +1,13 @@
1
+ module Loofah
2
+ module XML # :nodoc:
3
+ #
4
+ # Subclass of Nokogiri::XML::Document.
5
+ #
6
+ # See Loofah::ScrubBehavior and Loofah::DocumentDecorator for additional methods.
7
+ #
8
+ class Document < Nokogiri::XML::Document
9
+ include Loofah::ScrubBehavior::Node
10
+ include Loofah::DocumentDecorator
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ module Loofah
2
+ module XML # :nodoc:
3
+ #
4
+ # Subclass of Nokogiri::XML::DocumentFragment.
5
+ #
6
+ # See Loofah::ScrubBehavior for additional methods.
7
+ #
8
+ class DocumentFragment < Nokogiri::XML::DocumentFragment
9
+ class << self
10
+ #
11
+ # Overridden Nokogiri::XML::DocumentFragment
12
+ # constructor. Applications should use Loofah.fragment to
13
+ # parse a fragment.
14
+ #
15
+ def parse tags
16
+ doc = Loofah::XML::Document.new
17
+ doc.encoding = tags.encoding.name if tags.respond_to?(:encoding)
18
+ self.new(doc, tags)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,63 @@
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>
@@ -0,0 +1,502 @@
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
+ ]