sanitize 4.6.5 → 6.0.1

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

Potentially problematic release.


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

@@ -8,25 +8,22 @@ describe 'Sanitize::Transformers::CleanElement' do
8
8
  strings = {
9
9
  :basic => {
10
10
  :html => '<b>Lo<!-- comment -->rem</b> <a href="pants" title="foo" style="text-decoration: underline;">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br/>amet <style>.foo { color: #fff; }</style> <script>alert("hello world");</script>',
11
-
12
- :default => 'Lorem ipsum dolor sit amet .foo { color: #fff; } alert("hello world");',
13
- :restricted => '<b>Lorem</b> ipsum <strong>dolor</strong> sit amet .foo { color: #fff; } alert("hello world");',
14
- :basic => '<b>Lorem</b> <a href="pants" rel="nofollow">ipsum</a> <a href="http://foo.com/" rel="nofollow"><strong>dolor</strong></a> sit<br>amet .foo { color: #fff; } alert("hello world");',
15
- :relaxed => '<b>Lorem</b> <a href="pants" title="foo" style="text-decoration: underline;">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br>amet <style>.foo { color: #fff; }</style> alert("hello world");'
11
+ :default => 'Lorem ipsum dolor sit amet ',
12
+ :restricted => '<b>Lorem</b> ipsum <strong>dolor</strong> sit amet ',
13
+ :basic => '<b>Lorem</b> <a href="pants" rel="nofollow">ipsum</a> <a href="http://foo.com/" rel="nofollow"><strong>dolor</strong></a> sit<br>amet ',
14
+ :relaxed => '<b>Lorem</b> <a href="pants" title="foo" style="text-decoration: underline;">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br>amet <style>.foo { color: #fff; }</style> '
16
15
  },
17
16
 
18
17
  :malformed => {
19
18
  :html => 'Lo<!-- comment -->rem</b> <a href=pants title="foo>ipsum <a href="http://foo.com/"><strong>dolor</a></strong> sit<br/>amet <script>alert("hello world");',
20
-
21
- :default => 'Lorem dolor sit amet alert("hello world");',
22
- :restricted => 'Lorem <strong>dolor</strong> sit amet alert("hello world");',
23
- :basic => 'Lorem <a href="pants" rel="nofollow"><strong>dolor</strong></a> sit<br>amet alert("hello world");',
24
- :relaxed => 'Lorem <a href="pants" title="foo&gt;ipsum &lt;a href="><strong>dolor</strong></a> sit<br>amet alert("hello world");',
19
+ :default => 'Lorem dolor sit amet ',
20
+ :restricted => 'Lorem <strong>dolor</strong> sit amet ',
21
+ :basic => 'Lorem <a href="pants" rel="nofollow"><strong>dolor</strong></a> sit<br>amet ',
22
+ :relaxed => 'Lorem <a href="pants" title="foo>ipsum <a href="><strong>dolor</strong></a> sit<br>amet ',
25
23
  },
26
24
 
27
25
  :unclosed => {
28
26
  :html => '<p>a</p><blockquote>b',
29
-
30
27
  :default => ' a b ',
31
28
  :restricted => ' a b ',
32
29
  :basic => '<p>a</p><blockquote>b</blockquote>',
@@ -35,7 +32,6 @@ describe 'Sanitize::Transformers::CleanElement' do
35
32
 
36
33
  :malicious => {
37
34
  :html => '<b>Lo<!-- comment -->rem</b> <a href="javascript:pants" title="foo">ipsum</a> <a href="http://foo.com/"><strong>dolor</strong></a> sit<br/>amet <<foo>script>alert("hello world");</script>',
38
-
39
35
  :default => 'Lorem ipsum dolor sit amet &lt;script&gt;alert("hello world");',
40
36
  :restricted => '<b>Lorem</b> ipsum <strong>dolor</strong> sit amet &lt;script&gt;alert("hello world");',
41
37
  :basic => '<b>Lorem</b> <a rel="nofollow">ipsum</a> <a href="http://foo.com/" rel="nofollow"><strong>dolor</strong></a> sit<br>amet &lt;script&gt;alert("hello world");',
@@ -166,45 +162,95 @@ describe 'Sanitize::Transformers::CleanElement' do
166
162
  }
167
163
 
168
164
  describe 'Default config' do
169
- it 'should remove non-whitelisted elements, leaving safe contents behind' do
170
- Sanitize.fragment('foo <b>bar</b> <strong><a href="#a">baz</a></strong> quux')
165
+ it 'should remove non-allowlisted elements, leaving safe contents behind' do
166
+ _(Sanitize.fragment('foo <b>bar</b> <strong><a href="#a">baz</a></strong> quux'))
171
167
  .must_equal 'foo bar baz quux'
172
168
 
173
- Sanitize.fragment('<script>alert("<xss>");</script>')
174
- .must_equal 'alert("&lt;xss&gt;");'
169
+ _(Sanitize.fragment('<script>alert("<xss>");</script>'))
170
+ .must_equal ''
175
171
 
176
- Sanitize.fragment('<<script>script>alert("<xss>");</<script>>')
177
- .must_equal '&lt;script&gt;alert("&lt;xss&gt;");&lt;/&lt;script&gt;&gt;'
172
+ _(Sanitize.fragment('<<script>script>alert("<xss>");</<script>>'))
173
+ .must_equal '&lt;'
178
174
 
179
- Sanitize.fragment('< script <>> alert("<xss>");</script>')
175
+ _(Sanitize.fragment('< script <>> alert("<xss>");</script>'))
180
176
  .must_equal '&lt; script &lt;&gt;&gt; alert("");'
181
177
  end
182
178
 
183
179
  it 'should surround the contents of :whitespace_elements with space characters when removing the element' do
184
- Sanitize.fragment('foo<div>bar</div>baz')
180
+ _(Sanitize.fragment('foo<div>bar</div>baz'))
185
181
  .must_equal 'foo bar baz'
186
182
 
187
- Sanitize.fragment('foo<br>bar<br>baz')
183
+ _(Sanitize.fragment('foo<br>bar<br>baz'))
188
184
  .must_equal 'foo bar baz'
189
185
 
190
- Sanitize.fragment('foo<hr>bar<hr>baz')
186
+ _(Sanitize.fragment('foo<hr>bar<hr>baz'))
191
187
  .must_equal 'foo bar baz'
192
188
  end
193
189
 
194
190
  it 'should not choke on several instances of the same element in a row' do
195
- Sanitize.fragment('<img src="http://www.google.com/intl/en_ALL/images/logo.gif"><img src="http://www.google.com/intl/en_ALL/images/logo.gif"><img src="http://www.google.com/intl/en_ALL/images/logo.gif"><img src="http://www.google.com/intl/en_ALL/images/logo.gif">')
191
+ _(Sanitize.fragment('<img src="http://www.google.com/intl/en_ALL/images/logo.gif"><img src="http://www.google.com/intl/en_ALL/images/logo.gif"><img src="http://www.google.com/intl/en_ALL/images/logo.gif"><img src="http://www.google.com/intl/en_ALL/images/logo.gif">'))
192
+ .must_equal ''
193
+ end
194
+
195
+ it 'should not preserve the content of removed `iframe` elements' do
196
+ _(Sanitize.fragment('<iframe>hello! <script>alert(0)</script></iframe>'))
197
+ .must_equal ''
198
+ end
199
+
200
+ it 'should not preserve the content of removed `math` elements' do
201
+ _(Sanitize.fragment('<math>hello! <script>alert(0)</script></math>'))
202
+ .must_equal ''
203
+ end
204
+
205
+ it 'should not preserve the content of removed `noembed` elements' do
206
+ _(Sanitize.fragment('<noembed>hello! <script>alert(0)</script></noembed>'))
207
+ .must_equal ''
208
+ end
209
+
210
+ it 'should not preserve the content of removed `noframes` elements' do
211
+ _(Sanitize.fragment('<noframes>hello! <script>alert(0)</script></noframes>'))
212
+ .must_equal ''
213
+ end
214
+
215
+ it 'should not preserve the content of removed `noscript` elements' do
216
+ _(Sanitize.fragment('<noscript>hello! <script>alert(0)</script></noscript>'))
217
+ .must_equal ''
218
+ end
219
+
220
+ it 'should not preserve the content of removed `plaintext` elements' do
221
+ _(Sanitize.fragment('<plaintext>hello! <script>alert(0)</script>'))
222
+ .must_equal ''
223
+ end
224
+
225
+ it 'should not preserve the content of removed `script` elements' do
226
+ _(Sanitize.fragment('<script>hello! <script>alert(0)</script></script>'))
227
+ .must_equal ''
228
+ end
229
+
230
+ it 'should not preserve the content of removed `style` elements' do
231
+ _(Sanitize.fragment('<style>hello! <script>alert(0)</script></style>'))
232
+ .must_equal ''
233
+ end
234
+
235
+ it 'should not preserve the content of removed `svg` elements' do
236
+ _(Sanitize.fragment('<svg>hello! <script>alert(0)</script></svg>'))
237
+ .must_equal ''
238
+ end
239
+
240
+ it 'should not preserve the content of removed `xmp` elements' do
241
+ _(Sanitize.fragment('<xmp>hello! <script>alert(0)</script></xmp>'))
196
242
  .must_equal ''
197
243
  end
198
244
 
199
245
  strings.each do |name, data|
200
246
  it "should clean #{name} HTML" do
201
- Sanitize.fragment(data[:html]).must_equal(data[:default])
247
+ _(Sanitize.fragment(data[:html])).must_equal(data[:default])
202
248
  end
203
249
  end
204
250
 
205
251
  protocols.each do |name, data|
206
252
  it "should not allow #{name}" do
207
- Sanitize.fragment(data[:html]).must_equal(data[:default])
253
+ _(Sanitize.fragment(data[:html])).must_equal(data[:default])
208
254
  end
209
255
  end
210
256
  end
@@ -216,13 +262,13 @@ describe 'Sanitize::Transformers::CleanElement' do
216
262
 
217
263
  strings.each do |name, data|
218
264
  it "should clean #{name} HTML" do
219
- @s.fragment(data[:html]).must_equal(data[:restricted])
265
+ _(@s.fragment(data[:html])).must_equal(data[:restricted])
220
266
  end
221
267
  end
222
268
 
223
269
  protocols.each do |name, data|
224
270
  it "should not allow #{name}" do
225
- @s.fragment(data[:html]).must_equal(data[:restricted])
271
+ _(@s.fragment(data[:html])).must_equal(data[:restricted])
226
272
  end
227
273
  end
228
274
  end
@@ -233,24 +279,24 @@ describe 'Sanitize::Transformers::CleanElement' do
233
279
  end
234
280
 
235
281
  it 'should not choke on valueless attributes' do
236
- @s.fragment('foo <a href>foo</a> bar')
237
- .must_equal 'foo <a href rel="nofollow">foo</a> bar'
282
+ _(@s.fragment('foo <a href>foo</a> bar'))
283
+ .must_equal 'foo <a href="" rel="nofollow">foo</a> bar'
238
284
  end
239
285
 
240
286
  it 'should downcase attribute names' do
241
- @s.fragment('<a HREF="javascript:alert(\'foo\')">bar</a>')
287
+ _(@s.fragment('<a HREF="javascript:alert(\'foo\')">bar</a>'))
242
288
  .must_equal '<a rel="nofollow">bar</a>'
243
289
  end
244
290
 
245
291
  strings.each do |name, data|
246
292
  it "should clean #{name} HTML" do
247
- @s.fragment(data[:html]).must_equal(data[:basic])
293
+ _(@s.fragment(data[:html])).must_equal(data[:basic])
248
294
  end
249
295
  end
250
296
 
251
297
  protocols.each do |name, data|
252
298
  it "should not allow #{name}" do
253
- @s.fragment(data[:html]).must_equal(data[:basic])
299
+ _(@s.fragment(data[:html])).must_equal(data[:basic])
254
300
  end
255
301
  end
256
302
  end
@@ -261,110 +307,124 @@ describe 'Sanitize::Transformers::CleanElement' do
261
307
  end
262
308
 
263
309
  it 'should encode special chars in attribute values' do
264
- @s.fragment('<a href="http://example.com" title="<b>&eacute;xamples</b> & things">foo</a>')
265
- .must_equal '<a href="http://example.com" title="&lt;b&gt;éxamples&lt;/b&gt; &amp; things">foo</a>'
310
+ _(@s.fragment('<a href="http://example.com" title="<b>&eacute;xamples</b> & things">foo</a>'))
311
+ .must_equal '<a href="http://example.com" title="<bxamples</b> &amp; things">foo</a>'
266
312
  end
267
313
 
268
314
  strings.each do |name, data|
269
315
  it "should clean #{name} HTML" do
270
- @s.fragment(data[:html]).must_equal(data[:relaxed])
316
+ _(@s.fragment(data[:html])).must_equal(data[:relaxed])
271
317
  end
272
318
  end
273
319
 
274
320
  protocols.each do |name, data|
275
321
  it "should not allow #{name}" do
276
- @s.fragment(data[:html]).must_equal(data[:relaxed])
322
+ _(@s.fragment(data[:html])).must_equal(data[:relaxed])
277
323
  end
278
324
  end
279
325
  end
280
326
 
281
327
  describe 'Custom configs' do
282
- it 'should allow attributes on all elements if whitelisted under :all' do
328
+ it 'should allow attributes on all elements if allowlisted under :all' do
283
329
  input = '<p class="foo">bar</p>'
284
330
 
285
- Sanitize.fragment(input).must_equal ' bar '
331
+ _(Sanitize.fragment(input)).must_equal ' bar '
286
332
 
287
- Sanitize.fragment(input, {
333
+ _(Sanitize.fragment(input, {
288
334
  :elements => ['p'],
289
335
  :attributes => {:all => ['class']}
290
- }).must_equal input
336
+ })).must_equal input
291
337
 
292
- Sanitize.fragment(input, {
338
+ _(Sanitize.fragment(input, {
293
339
  :elements => ['p'],
294
340
  :attributes => {'div' => ['class']}
295
- }).must_equal '<p>bar</p>'
341
+ })).must_equal '<p>bar</p>'
296
342
 
297
- Sanitize.fragment(input, {
343
+ _(Sanitize.fragment(input, {
298
344
  :elements => ['p'],
299
345
  :attributes => {'p' => ['title'], :all => ['class']}
300
- }).must_equal input
346
+ })).must_equal input
301
347
  end
302
348
 
303
- it "should not allow relative URLs when relative URLs aren't whitelisted" do
349
+ it "should not allow relative URLs when relative URLs aren't allowlisted" do
304
350
  input = '<a href="/foo/bar">Link</a>'
305
351
 
306
- Sanitize.fragment(input,
352
+ _(Sanitize.fragment(input,
307
353
  :elements => ['a'],
308
354
  :attributes => {'a' => ['href']},
309
355
  :protocols => {'a' => {'href' => ['http']}}
310
- ).must_equal '<a>Link</a>'
356
+ )).must_equal '<a>Link</a>'
311
357
  end
312
358
 
313
359
  it 'should allow relative URLs containing colons when the colon is not in the first path segment' do
314
360
  input = '<a href="/wiki/Special:Random">Random Page</a>'
315
361
 
316
- Sanitize.fragment(input, {
362
+ _(Sanitize.fragment(input, {
317
363
  :elements => ['a'],
318
364
  :attributes => {'a' => ['href']},
319
365
  :protocols => {'a' => {'href' => [:relative]}}
320
- }).must_equal input
366
+ })).must_equal input
321
367
  end
322
368
 
323
369
  it 'should allow relative URLs containing colons when the colon is part of an anchor' do
324
370
  input = '<a href="#fn:1">Footnote 1</a>'
325
371
 
326
- Sanitize.fragment(input, {
372
+ _(Sanitize.fragment(input, {
327
373
  :elements => ['a'],
328
374
  :attributes => {'a' => ['href']},
329
375
  :protocols => {'a' => {'href' => [:relative]}}
330
- }).must_equal input
376
+ })).must_equal input
331
377
 
332
378
  input = '<a href="somepage#fn:1">Footnote 1</a>'
333
379
 
334
- Sanitize.fragment(input, {
380
+ _(Sanitize.fragment(input, {
335
381
  :elements => ['a'],
336
382
  :attributes => {'a' => ['href']},
337
383
  :protocols => {'a' => {'href' => [:relative]}}
338
- }).must_equal input
384
+ })).must_equal input
339
385
  end
340
386
 
341
387
  it 'should remove the contents of filtered nodes when :remove_contents is true' do
342
- Sanitize.fragment('foo bar <div>baz<span>quux</span></div>',
388
+ _(Sanitize.fragment('foo bar <div>baz<span>quux</span></div>',
343
389
  :remove_contents => true
344
- ).must_equal 'foo bar '
390
+ )).must_equal 'foo bar '
345
391
  end
346
392
 
347
- it 'should remove the contents of specified nodes when :remove_contents is an Array of element names as strings' do
348
- Sanitize.fragment('foo bar <div>baz<span>quux</span><script>alert("hello!");</script></div>',
393
+ it 'should remove the contents of specified nodes when :remove_contents is an Array or Set of element names as strings' do
394
+ _(Sanitize.fragment('foo bar <div>baz<span>quux</span> <b>hi</b><script>alert("hello!");</script></div>',
349
395
  :remove_contents => ['script', 'span']
350
- ).must_equal 'foo bar baz '
396
+ )).must_equal 'foo bar baz hi '
397
+
398
+ _(Sanitize.fragment('foo bar <div>baz<span>quux</span> <b>hi</b><script>alert("hello!");</script></div>',
399
+ :remove_contents => Set.new(['script', 'span'])
400
+ )).must_equal 'foo bar baz hi '
351
401
  end
352
402
 
353
- it 'should remove the contents of specified nodes when :remove_contents is an Array of element names as symbols' do
354
- Sanitize.fragment('foo bar <div>baz<span>quux</span><script>alert("hello!");</script></div>',
403
+ it 'should remove the contents of specified nodes when :remove_contents is an Array or Set of element names as symbols' do
404
+ _(Sanitize.fragment('foo bar <div>baz<span>quux</span> <b>hi</b><script>alert("hello!");</script></div>',
355
405
  :remove_contents => [:script, :span]
356
- ).must_equal 'foo bar baz '
406
+ )).must_equal 'foo bar baz hi '
407
+
408
+ _(Sanitize.fragment('foo bar <div>baz<span>quux</span> <b>hi</b><script>alert("hello!");</script></div>',
409
+ :remove_contents => Set.new([:script, :span])
410
+ )).must_equal 'foo bar baz hi '
411
+ end
412
+
413
+ it 'should remove the contents of allowlisted iframes' do
414
+ _(Sanitize.fragment('<iframe>hi <script>hello</script></iframe>',
415
+ :elements => ['iframe']
416
+ )).must_equal '<iframe></iframe>'
357
417
  end
358
418
 
359
419
  it 'should not allow arbitrary HTML5 data attributes by default' do
360
- Sanitize.fragment('<b data-foo="bar"></b>',
420
+ _(Sanitize.fragment('<b data-foo="bar"></b>',
361
421
  :elements => ['b']
362
- ).must_equal '<b></b>'
422
+ )).must_equal '<b></b>'
363
423
 
364
- Sanitize.fragment('<b class="foo" data-foo="bar"></b>',
424
+ _(Sanitize.fragment('<b class="foo" data-foo="bar"></b>',
365
425
  :attributes => {'b' => ['class']},
366
426
  :elements => ['b']
367
- ).must_equal '<b class="foo"></b>'
427
+ )).must_equal '<b class="foo"></b>'
368
428
  end
369
429
 
370
430
  it 'should allow arbitrary HTML5 data attributes when the :attributes config includes :data' do
@@ -373,28 +433,28 @@ describe 'Sanitize::Transformers::CleanElement' do
373
433
  :elements => ['b']
374
434
  )
375
435
 
376
- s.fragment('<b data-foo="valid" data-bar="valid"></b>')
436
+ _(s.fragment('<b data-foo="valid" data-bar="valid"></b>'))
377
437
  .must_equal '<b data-foo="valid" data-bar="valid"></b>'
378
438
 
379
- s.fragment('<b data-="invalid"></b>')
439
+ _(s.fragment('<b data-="invalid"></b>'))
380
440
  .must_equal '<b></b>'
381
441
 
382
- s.fragment('<b data-="invalid"></b>')
442
+ _(s.fragment('<b data-="invalid"></b>'))
383
443
  .must_equal '<b></b>'
384
444
 
385
- s.fragment('<b data-xml="invalid"></b>')
445
+ _(s.fragment('<b data-xml="invalid"></b>'))
386
446
  .must_equal '<b></b>'
387
447
 
388
- s.fragment('<b data-xmlfoo="invalid"></b>')
448
+ _(s.fragment('<b data-xmlfoo="invalid"></b>'))
389
449
  .must_equal '<b></b>'
390
450
 
391
- s.fragment('<b data-f:oo="valid"></b>')
451
+ _(s.fragment('<b data-f:oo="valid"></b>'))
392
452
  .must_equal '<b></b>'
393
453
 
394
- s.fragment('<b data-f/oo="partial"></b>')
454
+ _(s.fragment('<b data-f/oo="partial"></b>'))
395
455
  .must_equal '<b data-f=""></b>' # Nokogiri quirk; not ideal, but harmless
396
456
 
397
- s.fragment('<b data-éfoo="valid"></b>')
457
+ _(s.fragment('<b data-éfoo="valid"></b>'))
398
458
  .must_equal '<b></b>' # Another annoying Nokogiri quirk.
399
459
  end
400
460
 
@@ -407,28 +467,86 @@ describe 'Sanitize::Transformers::CleanElement' do
407
467
  }
408
468
  )
409
469
 
410
- s.fragment('<p>foo</p>').must_equal "\nfoo\n"
411
- s.fragment('<p>foo</p><p>bar</p>').must_equal "\nfoo\n\nbar\n"
412
- s.fragment('foo<div>bar</div>baz').must_equal "foo\nbar\nbaz"
413
- s.fragment('foo<br>bar<br>baz').must_equal "foo\nbar\nbaz"
470
+ _(s.fragment('<p>foo</p>')).must_equal "\nfoo\n"
471
+ _(s.fragment('<p>foo</p><p>bar</p>')).must_equal "\nfoo\n\nbar\n"
472
+ _(s.fragment('foo<div>bar</div>baz')).must_equal "foo\nbar\nbaz"
473
+ _(s.fragment('foo<br>bar<br>baz')).must_equal "foo\nbar\nbaz"
414
474
  end
415
475
 
416
- it 'handles protocols correctly regardless of case' do
476
+ it 'should handle protocols correctly regardless of case' do
417
477
  input = '<a href="hTTpS://foo.com/">Text</a>'
418
478
 
419
- Sanitize.fragment(input, {
479
+ _(Sanitize.fragment(input, {
420
480
  :elements => ['a'],
421
481
  :attributes => {'a' => ['href']},
422
482
  :protocols => {'a' => {'href' => ['https']}}
423
- }).must_equal input
483
+ })).must_equal input
424
484
 
425
485
  input = '<a href="mailto:someone@example.com?Subject=Hello">Text</a>'
426
486
 
427
- Sanitize.fragment(input, {
487
+ _(Sanitize.fragment(input, {
428
488
  :elements => ['a'],
429
489
  :attributes => {'a' => ['href']},
430
490
  :protocols => {'a' => {'href' => ['https']}}
431
- }).must_equal "<a>Text</a>"
491
+ })).must_equal "<a>Text</a>"
432
492
  end
493
+
494
+ it 'should sanitize protocols in data attributes even if data attributes are generically allowed' do
495
+ input = '<a data-url="mailto:someone@example.com">Text</a>'
496
+
497
+ _(Sanitize.fragment(input, {
498
+ :elements => ['a'],
499
+ :attributes => {'a' => [:data]},
500
+ :protocols => {'a' => {'data-url' => ['https']}}
501
+ })).must_equal "<a>Text</a>"
502
+
503
+ _(Sanitize.fragment(input, {
504
+ :elements => ['a'],
505
+ :attributes => {'a' => [:data]},
506
+ :protocols => {'a' => {'data-url' => ['mailto']}}
507
+ })).must_equal input
508
+ end
509
+
510
+ it 'should prevent `<meta>` tags from being used to set a non-UTF-8 charset' do
511
+ _(Sanitize.document('<html><head><meta charset="utf-8"></head><body>Howdy!</body></html>',
512
+ :elements => %w[html head meta body],
513
+ :attributes => {'meta' => ['charset']}
514
+ )).must_equal "<html><head><meta charset=\"utf-8\"></head><body>Howdy!</body></html>"
515
+
516
+ _(Sanitize.document('<html><meta charset="utf-8">Howdy!</html>',
517
+ :elements => %w[html meta],
518
+ :attributes => {'meta' => ['charset']}
519
+ )).must_equal "<html><meta charset=\"utf-8\">Howdy!</html>"
520
+
521
+ _(Sanitize.document('<html><meta charset="us-ascii">Howdy!</html>',
522
+ :elements => %w[html meta],
523
+ :attributes => {'meta' => ['charset']}
524
+ )).must_equal "<html><meta charset=\"utf-8\">Howdy!</html>"
525
+
526
+ _(Sanitize.document('<html><meta http-equiv="content-type" content=" text/html; charset=us-ascii">Howdy!</html>',
527
+ :elements => %w[html meta],
528
+ :attributes => {'meta' => %w[content http-equiv]}
529
+ )).must_equal "<html><meta http-equiv=\"content-type\" content=\" text/html;charset=utf-8\">Howdy!</html>"
530
+
531
+ _(Sanitize.document('<html><meta http-equiv="Content-Type" content="text/plain;charset = us-ascii">Howdy!</html>',
532
+ :elements => %w[html meta],
533
+ :attributes => {'meta' => %w[content http-equiv]}
534
+ )).must_equal "<html><meta http-equiv=\"Content-Type\" content=\"text/plain;charset=utf-8\">Howdy!</html>"
535
+ end
536
+
537
+ it 'should not modify `<meta>` tags that already set a UTF-8 charset' do
538
+ _(Sanitize.document('<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"></head><body>Howdy!</body></html>',
539
+ :elements => %w[html head meta body],
540
+ :attributes => {'meta' => %w[content http-equiv]}
541
+ )).must_equal "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"></head><body>Howdy!</body></html>"
542
+ end
543
+
544
+ it 'always removes `<noscript>` elements even if `noscript` is in the allowlist' do
545
+ assert_equal(
546
+ '',
547
+ Sanitize.fragment('<noscript>foo</noscript>', elements: ['noscript'])
548
+ )
549
+ end
550
+
433
551
  end
434
552
  end
data/test/test_config.rb CHANGED
@@ -6,7 +6,7 @@ describe 'Config' do
6
6
  parallelize_me!
7
7
 
8
8
  def verify_deeply_frozen(config)
9
- config.must_be :frozen?
9
+ _(config).must_be :frozen?
10
10
 
11
11
  if Hash === config
12
12
  config.each_value {|v| verify_deeply_frozen(v) }
@@ -27,7 +27,7 @@ describe 'Config' do
27
27
  a = {:one => {:one_one => [0, '1', :a], :one_two => false, :one_three => Set.new([:a, :b, :c])}}
28
28
  b = Sanitize::Config.freeze_config(a)
29
29
 
30
- b.must_be_same_as a
30
+ _(b).must_be_same_as a
31
31
  verify_deeply_frozen a
32
32
  end
33
33
  end
@@ -40,10 +40,10 @@ describe 'Config' do
40
40
 
41
41
  c = Sanitize::Config.merge(a, b)
42
42
 
43
- c.wont_be_same_as a
44
- c.wont_be_same_as b
43
+ _(c).wont_be_same_as a
44
+ _(c).wont_be_same_as b
45
45
 
46
- c.must_equal(
46
+ _(c).must_equal(
47
47
  :one => {
48
48
  :one_one => [0, '1', :a],
49
49
  :one_two => true,
@@ -53,13 +53,13 @@ describe 'Config' do
53
53
  :two => 2
54
54
  )
55
55
 
56
- c[:one].wont_be_same_as a[:one]
57
- c[:one][:one_one].wont_be_same_as a[:one][:one_one]
56
+ _(c[:one]).wont_be_same_as a[:one]
57
+ _(c[:one][:one_one]).wont_be_same_as a[:one][:one_one]
58
58
  end
59
59
 
60
60
  it 'should raise an ArgumentError if either argument is not a Hash' do
61
- proc { Sanitize::Config.merge('foo', {}) }.must_raise ArgumentError
62
- proc { Sanitize::Config.merge({}, 'foo') }.must_raise ArgumentError
61
+ _(proc { Sanitize::Config.merge('foo', {}) }).must_raise ArgumentError
62
+ _(proc { Sanitize::Config.merge({}, 'foo') }).must_raise ArgumentError
63
63
  end
64
64
  end
65
65
  end
@@ -16,27 +16,27 @@ describe 'Malicious CSS' do
16
16
  end
17
17
 
18
18
  it 'should not be possible to inject an expression by munging it with a comment' do
19
- @s.properties(%[width:expr/*XSS*/ession(alert('XSS'))]).
19
+ _(@s.properties(%[width:expr/*XSS*/ession(alert('XSS'))])).
20
20
  must_equal ''
21
21
 
22
- @s.properties(%[width:ex/*XSS*//*/*/pression(alert("XSS"))]).
22
+ _(@s.properties(%[width:ex/*XSS*//*/*/pression(alert("XSS"))])).
23
23
  must_equal ''
24
24
  end
25
25
 
26
26
  it 'should not be possible to inject an expression by munging it with a newline' do
27
- @s.properties(%[width:\nexpression(alert('XSS'));]).
27
+ _(@s.properties(%[width:\nexpression(alert('XSS'));])).
28
28
  must_equal ''
29
29
  end
30
30
 
31
31
  it 'should not allow the javascript protocol' do
32
- @s.properties(%[background-image:url("javascript:alert('XSS')");]).
32
+ _(@s.properties(%[background-image:url("javascript:alert('XSS')");])).
33
33
  must_equal ''
34
34
 
35
- Sanitize.fragment(%[<div style="background-image: url(&#1;javascript:alert('XSS'))">],
36
- Sanitize::Config::RELAXED).must_equal '<div></div>'
35
+ _(Sanitize.fragment(%[<div style="background-image: url(&#1;javascript:alert('XSS'))">],
36
+ Sanitize::Config::RELAXED)).must_equal '<div></div>'
37
37
  end
38
38
 
39
39
  it 'should not allow behaviors' do
40
- @s.properties(%[behavior: url(xss.htc);]).must_equal ''
40
+ _(@s.properties(%[behavior: url(xss.htc);])).must_equal ''
41
41
  end
42
42
  end