Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(155)

Side by Side Diff: tests/html/node_validator_test.dart

Issue 1080583003: Emphasize that the XSS tests should not be casually suppressed (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Review fixes Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tests/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library validator_test;
6
7 import 'dart:html';
8 import 'dart:svg' as svg;
9 import 'package:unittest/unittest.dart';
10 import 'package:unittest/html_individual_config.dart';
11 import 'utils.dart';
12
13
14 var nullSanitizer = new NullTreeSanitizer();
15
16 void validateHtml(String html, String reference, NodeValidator validator) {
17 var a = document.body.createFragment(html, validator: validator);
18 var b = document.body.createFragment(reference,
19 treeSanitizer: nullSanitizer);
20
21 // Prevent a false pass when both the html and the reference both get entirely
22 // deleted, which is technically a match, but unlikely to be what we meant.
23 if (reference != '') {
24 expect(b.childNodes.length > 0, isTrue);
25 }
26 validateNodeTree(a, b);
27 }
28
29 class RecordingUriValidator implements UriPolicy {
30 final List<String> calls = <String>[];
31
32 bool allowsUri(String uri) {
33 calls.add('$uri');
34 return false;
35 }
36
37 void reset() {
38 calls.clear();
39 }
40 }
41
42 void testHtml(String name, NodeValidator validator, String html,
43 [String reference]) {
44 test(name, () {
45 if (reference == null) {
46 reference = html;
47 }
48
49 validateHtml(html, reference, validator);
50 });
51 }
52
53 main() {
54 useHtmlIndividualConfiguration();
55
56 group('DOM_sanitization', () {
57 var validator = new NodeValidatorBuilder.common();
58
59 testHtml('allows simple constructs',
60 validator,
61 '<div class="baz">something</div>');
62
63 testHtml('blocks unknown attributes',
64 validator,
65 '<div foo="baz">something</div>',
66 '<div>something</div>');
67
68 testHtml('blocks custom element',
69 validator,
70 '<x-my-element>something</x-my-element>',
71 '');
72
73 testHtml('blocks custom is element',
74 validator,
75 '<div is="x-my-element">something</div>',
76 '');
77
78 testHtml('blocks body elements',
79 validator,
80 '<body background="s"></body>',
81 '');
82
83 testHtml('allows select elements',
84 validator,
85 '<select>'
86 '<option>a</option>'
87 '</select>');
88
89 testHtml('blocks sequential script elements',
90 validator,
91 '<div><script></script><script></script></div>',
92 '<div></div>');
93
94 testHtml('blocks inline styles',
95 validator,
96 '<div style="background: red"></div>',
97 '<div></div>');
98
99 testHtml('blocks namespaced attributes',
100 validator,
101 '<div ns:foo="foo"></div>',
102 '<div></div>');
103
104 testHtml('blocks namespaced common attributes',
105 validator,
106 '<div ns:class="foo"></div>',
107 '<div></div>');
108
109 testHtml('blocks namespaced common elements',
110 validator,
111 '<ns:div></ns:div>',
112 '');
113
114 testHtml('allows CDATA sections',
115 validator,
116 '<span>![CDATA[ some text ]]></span>');
117
118 test('sanitizes template contents', () {
119 if (!TemplateElement.supported) return;
120
121 var html = '<template>'
122 '<div></div>'
123 '<script></script>'
124 '<img src="http://example.com/foo"/>'
125 '</template>';
126
127 var fragment = document.body.createFragment(html, validator: validator);
128 var template = fragment.nodes.single;
129
130 var expectedContent = document.body.createFragment(
131 '<div></div>'
132 '<img/>');
133
134 validateNodeTree(template.content, expectedContent);
135 });
136 });
137
138 group('URI_sanitization', () {
139 var recorder = new RecordingUriValidator();
140 var validator = new NodeValidatorBuilder()..allowHtml5(uriPolicy: recorder);
141
142 checkUriPolicyCalls(String name, String html, String reference,
143 List<String> expectedCalls) {
144
145 test(name, () {
146 recorder.reset();
147
148 validateHtml(html, reference, validator);
149 expect(recorder.calls, expectedCalls);
150 });
151 }
152
153 checkUriPolicyCalls('a::href',
154 '<a href="s"></a>',
155 '<a></a>',
156 ['s']);
157
158 checkUriPolicyCalls('area::href',
159 '<area href="s"></area>',
160 '<area></area>',
161 ['s']);
162
163 checkUriPolicyCalls('blockquote::cite',
164 '<blockquote cite="s"></blockquote>',
165 '<blockquote></blockquote>',
166 ['s']);
167 checkUriPolicyCalls('command::icon',
168 '<command icon="s"/>',
169 '<command/>',
170 ['s']);
171 checkUriPolicyCalls('img::src',
172 '<img src="s"/>',
173 '<img/>',
174 ['s']);
175 checkUriPolicyCalls('input::src',
176 '<input src="s"/>',
177 '<input/>',
178 ['s']);
179 checkUriPolicyCalls('ins::cite',
180 '<ins cite="s"></ins>',
181 '<ins></ins>',
182 ['s']);
183 checkUriPolicyCalls('q::cite',
184 '<q cite="s"></q>',
185 '<q></q>',
186 ['s']);
187 checkUriPolicyCalls('video::poster',
188 '<video poster="s"/>',
189 '<video/>',
190 ['s']);
191 });
192
193 group('allowNavigation', () {
194 var validator = new NodeValidatorBuilder()..allowNavigation();
195
196 testHtml('allows anchor tags',
197 validator,
198 '<a href="#foo">foo</a>');
199
200 testHtml('allows form elements',
201 validator,
202 '<form method="post" action="/foo"></form>');
203
204 testHtml('disallows script navigation',
205 validator,
206 '<a href="javascript:foo = 1">foo</a>',
207 '<a>foo</a>');
208
209 testHtml('disallows cross-site navigation',
210 validator,
211 '<a href="http://example.com">example.com</a>',
212 '<a>example.com</a>');
213
214 testHtml('blocks other elements',
215 validator,
216 '<a href="#foo"><b>foo</b></a>',
217 '<a href="#foo"></a>');
218
219 testHtml('blocks tag extension',
220 validator,
221 '<a is="x-foo"></a>',
222 '');
223 });
224
225 group('allowImages', () {
226 var validator = new NodeValidatorBuilder()..allowImages();
227
228 testHtml('allows images',
229 validator,
230 '<img src="/foo.jpg" alt="something" width="100" height="100"/>');
231
232 testHtml('blocks onerror',
233 validator,
234 '<img src="/foo.jpg" onerror="something"/>',
235 '<img src="/foo.jpg"/>');
236
237 testHtml('enforces same-origin',
238 validator,
239 '<img src="http://example.com/foo.jpg"/>',
240 '<img/>');
241 });
242
243 group('allowCustomElement', () {
244 var validator = new NodeValidatorBuilder()
245 ..allowCustomElement(
246 'x-foo',
247 attributes: ['bar'],
248 uriAttributes: ['baz'])
249 ..allowHtml5();
250
251 testHtml('allows custom elements',
252 validator,
253 '<x-foo bar="something" baz="/foo.jpg"></x-foo>');
254
255
256 testHtml('validates custom tag URIs',
257 validator,
258 '<x-foo baz="http://example.com/foo.jpg"></x-foo>',
259 '<x-foo></x-foo>');
260
261 testHtml('blocks type extensions',
262 validator,
263 '<div is="x-foo"></div>',
264 '');
265
266 testHtml('blocks tags on non-matching elements',
267 validator,
268 '<div bar="foo"></div>',
269 '<div></div>');
270 });
271
272 group('allowTagExtension', () {
273 var validator = new NodeValidatorBuilder()
274 ..allowTagExtension(
275 'x-foo',
276 'div',
277 attributes: ['bar'],
278 uriAttributes: ['baz'])
279 ..allowHtml5();
280
281 testHtml('allows tag extensions',
282 validator,
283 '<div is="x-foo" bar="something" baz="/foo.jpg"></div>');
284
285 testHtml('blocks custom elements',
286 validator,
287 '<x-foo></x-foo>',
288 '');
289
290 testHtml('validates tag extension URIs',
291 validator,
292 '<div is="x-foo" baz="http://example.com/foo.jpg"></div>',
293 '<div is="x-foo"></div>');
294
295 testHtml('blocks tags on non-matching elements',
296 validator,
297 '<div bar="foo"></div>',
298 '<div></div>');
299
300 testHtml('blocks non-matching tags',
301 validator,
302 '<span is="x-foo">something</span>',
303 '');
304
305 validator = new NodeValidatorBuilder()
306 ..allowTagExtension(
307 'x-foo',
308 'div',
309 attributes: ['bar'],
310 uriAttributes: ['baz'])
311 ..allowTagExtension(
312 'x-else',
313 'div');
314
315 testHtml('blocks tags on non-matching custom elements',
316 validator,
317 '<div bar="foo" is="x-else"></div>',
318 '<div is="x-else"></div>');
319 });
320
321 group('allowTemplating', () {
322 var validator = new NodeValidatorBuilder()
323 ..allowTemplating()
324 ..allowHtml5();
325
326 testHtml('allows templates',
327 validator,
328 '<template bind="{{a}}"></template>');
329
330 testHtml('allows template attributes',
331 validator,
332 '<template bind="{{a}}" ref="foo" repeat="{{}}" if="{{}}" syntax="foo">< /template>');
333
334 testHtml('allows template attribute',
335 validator,
336 '<div template repeat="{{}}"></div>');
337
338 testHtml('blocks illegal template attribute',
339 validator,
340 '<div template="foo" repeat="{{}}"></div>',
341 '<div></div>');
342 });
343
344 group('allowSvg', () {
345 var validator = new NodeValidatorBuilder()
346 ..allowSvg()
347 ..allowTextElements();
348
349 testHtml('allows basic SVG',
350 validator,
351 '<svg xmlns="http://www.w3.org/2000/svg'
352 'xmlns:xlink="http://www.w3.org/1999/xlink">'
353 '<image xlink:href="foo" data-foo="bar"/>'
354 '</svg>');
355
356 testHtml('blocks script elements',
357 validator,
358 '<svg xmlns="http://www.w3.org/2000/svg>'
359 '<script></script>'
360 '</svg>',
361 '');
362
363 testHtml('blocks script elements but allows other',
364 validator,
365 '<svg xmlns="http://www.w3.org/2000/svg>'
366 '<script></script><ellipse cx="200" cy="80" rx="100" ry="50"></ellipse>'
367 '</svg>',
368 '<svg xmlns="http://www.w3.org/2000/svg>'
369 '<ellipse cx="200" cy="80" rx="100" ry="50"></ellipse>'
370 '</svg>');
371
372 testHtml('blocks script handlers',
373 validator,
374 '<svg xmlns="http://www.w3.org/2000/svg'
375 'xmlns:xlink="http://www.w3.org/1999/xlink">'
376 '<image xlink:href="foo" onerror="something"/>'
377 '</svg>',
378 '<svg xmlns="http://www.w3.org/2000/svg'
379 'xmlns:xlink="http://www.w3.org/1999/xlink">'
380 '<image xlink:href="foo"/>'
381 '</svg>');
382
383 testHtml('blocks foreignObject content',
384 validator,
385 '<svg xmlns="http://www.w3.org/2000/svg">'
386 '<foreignobject width="100" height="150">'
387 '<body xmlns="http://www.w3.org/1999/xhtml">'
388 '<div>Some content</div>'
389 '</body>'
390 '</foreignobject>'
391 '<b>42</b>'
392 '</svg>',
393 '<svg xmlns="http://www.w3.org/2000/svg">'
394 '<b>42</b>'
395 '</svg>');
396 });
397
398 group('allowInlineStyles', () {
399 var validator = new NodeValidatorBuilder()
400 ..allowTextElements()
401 ..allowInlineStyles();
402
403 testHtml('allows inline styles',
404 validator,
405 '<span style="background-color:red">text</span>');
406
407 testHtml('blocks other attributes',
408 validator,
409 '<span class="red-span"></span>',
410 '<span></span>');
411
412 validator = new NodeValidatorBuilder()
413 ..allowTextElements()
414 ..allowInlineStyles(tagName: 'span');
415
416 testHtml('scoped allows inline styles on spans',
417 validator,
418 '<span style="background-color:red">text</span>');
419
420 testHtml('scoped blocks inline styles on LIs',
421 validator,
422 '<li style="background-color:red">text</li>',
423 '<li>text</li>');
424 });
425
426 group('throws', () {
427 var validator = new NodeValidator.throws(new NodeValidatorBuilder.common());
428
429 var validationError = throwsArgumentError;
430
431 test('does not throw on valid syntax', () {
432 expect(() {
433 document.body.createFragment('<div></div>', validator: validator);
434 }, returnsNormally);
435 });
436
437 test('throws on invalid elements', () {
438 expect(() {
439 document.body.createFragment('<foo></foo>', validator: validator);
440 }, validationError);
441 });
442
443 test('throws on invalid attributes', () {
444 expect(() {
445 document.body.createFragment('<div foo="bar"></div>',
446 validator: validator);
447 }, validationError);
448 });
449
450 test('throws on invalid attribute values', () {
451 expect(() {
452 document.body.createFragment('<img src="http://example.com/foo.jpg"/>',
453 validator: validator);
454 }, validationError);
455 });
456 });
457
458 group('svg', () {
459 test('parsing', () {
460 var svgText =
461 '<svg xmlns="http://www.w3.org/2000/svg'
462 'xmlns:xlink="http://www.w3.org/1999/xlink">'
463 '<image xlink:href="foo" data-foo="bar"/>'
464 '</svg>';
465
466 var fragment = new DocumentFragment.svg(svgText);
467 var element = fragment.nodes.first;
468 expect(element is svg.SvgSvgElement, isTrue);
469 expect(element.children[0] is svg.ImageElement, isTrue);
470 });
471 });
472
473 group('dom_clobbering', () {
474 var validator = new NodeValidatorBuilder.common();
475
476 testHtml('DOM clobbering of attributes with single node',
477 validator,
478 "<form onmouseover='alert(1)'><input name='attributes'>",
479 "");
480
481 testHtml('DOM clobbering of attributes with multiple nodes',
482 validator,
483 "<form onmouseover='alert(1)'><input name='attributes'>"
484 "<input name='attributes'>",
485 "");
486
487 testHtml('DOM clobbering of lastChild',
488 validator,
489 "<form><input name='lastChild'><input onmouseover='alert(1)'>",
490 "");
491
492 testHtml('DOM clobbering of both children and lastChild',
493 validator,
494 "<form><input name='lastChild'><input name='children'>"
495 "<input id='children'><input onmouseover='alert(1)'>",
496 "");
497
498 testHtml('DOM clobbering of both children and lastChild, different order',
499 validator,
500 "<form><input name='children'><input name='children'>"
501 "<input id='children' name='lastChild'>"
502 "<input id='bad' onmouseover='alert(1)'>",
503 "");
504
505 testHtml('tagName makes containing form invalid',
506 validator,
507 "<form onmouseover='alert(2)'><input name='tagName'>",
508 "");
509
510 testHtml('tagName without mouseover',
511 validator,
512 "<form><input name='tagName'>",
513 "");
514 });
515 }
OLDNEW
« no previous file with comments | « tests/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698