dompurify 2.2.7 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,11 +6,11 @@
6
6
 
7
7
  DOMPurify is a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG.
8
8
 
9
- It's also very simple to use and get started with. DOMPurify was [started in February 2014](https://github.com/cure53/DOMPurify/commit/a630922616927373485e0e787ab19e73e3691b2b) and, meanwhile, has reached version 2.2.7.
9
+ It's also very simple to use and get started with. DOMPurify was [started in February 2014](https://github.com/cure53/DOMPurify/commit/a630922616927373485e0e787ab19e73e3691b2b) and, meanwhile, has reached version 2.3.1.
10
10
 
11
11
  DOMPurify is written in JavaScript and works in all modern browsers (Safari (10+), Opera (15+), Internet Explorer (10+), Edge, Firefox and Chrome - as well as almost anything else using Blink or WebKit). It doesn't break on MSIE6 or other legacy browsers. It either uses [a fall-back](#what-about-older-browsers-like-msie8) or simply does nothing.
12
12
 
13
- Our automated tests cover [15 different browsers](https://github.com/cure53/DOMPurify/blob/main/test/karma.custom-launchers.config.js#L5) right now, more to come. We also cover Node.js v14.15.1, v15.4.0, running DOMPurify on [jsdom](https://github.com/tmpvar/jsdom). Older Node.js versions are known to work as well.
13
+ Our automated tests cover [17 different browsers](https://github.com/cure53/DOMPurify/blob/main/test/karma.custom-launchers.config.js#L5) right now, more to come. We also cover Node.js v14.15.1, v15.4.0, running DOMPurify on [jsdom](https://github.com/tmpvar/jsdom). Older Node.js versions are known to work as well.
14
14
 
15
15
  DOMPurify is written by security people who have vast background in web attacks and XSS. Fear not. For more details please also read about our [Security Goals & Threat Model](https://github.com/cure53/DOMPurify/wiki/Security-Goals-&-Threat-Model). Please, read it. Like, really.
16
16
 
@@ -170,6 +170,9 @@ var clean = DOMPurify.sanitize(dirty, {USE_PROFILES: {svg: true, svgFilters: tru
170
170
  // allow all safe MathML elements and SVG, but no SVG Filters
171
171
  var clean = DOMPurify.sanitize(dirty, {USE_PROFILES: {mathMl: true, svg: true}});
172
172
 
173
+ // change the default namespace from HTML to something different
174
+ var clean = DOMPurify.sanitize(dirty, {NAMESPACE: 'http://www.w3.org/2000/svg'});
175
+
173
176
  // leave all safe HTML as it is and add <style> elements to block-list
174
177
  var clean = DOMPurify.sanitize(dirty, {FORBID_TAGS: ['style']});
175
178
 
@@ -334,7 +337,7 @@ Feature releases will not be announced to this list.
334
337
 
335
338
  Many people helped and help DOMPurify become what it is and need to be acknowledged here!
336
339
 
337
- [granlem 💸](https://twitter.com/MaximeVeit), [oreoshake 💸](https://github.com/oreoshake), [dcramer 💸](https://github.com/dcramer),[tdeekens ❤️](https://github.com/tdeekens), [peernohell ❤️](https://github.com/peernohell), [neilj](https://github.com/neilj), [fhemberger](https://github.com/fhemberger), [Joris-van-der-Wel](https://github.com/Joris-van-der-Wel), [ydaniv](https://github.com/ydaniv), [terjanq](https://twitter.com/terjanq), [filedescriptor](https://github.com/filedescriptor), [ConradIrwin](https://github.com/ConradIrwin), [gibson042](https://github.com/gibson042), [choumx](https://github.com/choumx), [0xSobky](https://github.com/0xSobky), [styfle](https://github.com/styfle), [koto](https://github.com/koto), [tlau88](https://github.com/tlau88), [strugee](https://github.com/strugee), [oparoz](https://github.com/oparoz), [mathiasbynens](https://github.com/mathiasbynens), [edg2s](https://github.com/edg2s), [dnkolegov](https://github.com/dnkolegov), [dhardtke](https://github.com/dhardtke), [wirehead](https://github.com/wirehead), [thorn0](https://github.com/thorn0), [styu](https://github.com/styu), [mozfreddyb](https://github.com/mozfreddyb), [mikesamuel](https://github.com/mikesamuel), [jorangreef](https://github.com/jorangreef), [jimmyhchan](https://github.com/jimmyhchan), [jameydeorio](https://github.com/jameydeorio), [jameskraus](https://github.com/jameskraus), [hyderali](https://github.com/hyderali), [hansottowirtz](https://github.com/hansottowirtz), [hackvertor](https://github.com/hackvertor), [freddyb](https://github.com/freddyb), [flavorjones](https://github.com/flavorjones), [djfarrelly](https://github.com/djfarrelly), [devd](https://github.com/devd), [camerondunford](https://github.com/camerondunford), [buu700](https://github.com/buu700), [buildog](https://github.com/buildog), [alabiaga](https://github.com/alabiaga), [Vector919](https://github.com/Vector919), [Robbert](https://github.com/Robbert), [GreLI](https://github.com/GreLI), [FuzzySockets](https://github.com/FuzzySockets), [ArtemBernatskyy](https://github.com/ArtemBernatskyy), [@garethheyes](https://twitter.com/garethheyes), [@shafigullin](https://twitter.com/shafigullin), [@mmrupp](https://twitter.com/mmrupp), [@irsdl](https://twitter.com/irsdl),[ShikariSenpai](https://github.com/ShikariSenpai), [ansjdnakjdnajkd](https://github.com/ansjdnakjdnajkd), [@asutherland](https://twitter.com/asutherland), [@mathias](https://twitter.com/mathias), [@cgvwzq](https://twitter.com/cgvwzq), [@robbertatwork](https://twitter.com/robbertatwork), [@giutro](https://twitter.com/giutro), [@CmdEngineer_](https://twitter.com/CmdEngineer_), [@avr4mit](https://twitter.com/avr4mit) and especially [@securitymb ❤️](https://twitter.com/securitymb) & [@masatokinugawa ❤️](https://twitter.com/masatokinugawa)
340
+ [granlem 💸](https://twitter.com/MaximeVeit), [oreoshake 💸](https://github.com/oreoshake), [dcramer 💸](https://github.com/dcramer),[tdeekens ❤️](https://github.com/tdeekens), [peernohell ❤️](https://github.com/peernohell), [NateScarlet](https://github.com/NateScarlet), [neilj](https://github.com/neilj), [fhemberger](https://github.com/fhemberger), [Joris-van-der-Wel](https://github.com/Joris-van-der-Wel), [ydaniv](https://github.com/ydaniv), [terjanq](https://twitter.com/terjanq), [filedescriptor](https://github.com/filedescriptor), [ConradIrwin](https://github.com/ConradIrwin), [gibson042](https://github.com/gibson042), [choumx](https://github.com/choumx), [0xSobky](https://github.com/0xSobky), [styfle](https://github.com/styfle), [koto](https://github.com/koto), [tlau88](https://github.com/tlau88), [strugee](https://github.com/strugee), [oparoz](https://github.com/oparoz), [mathiasbynens](https://github.com/mathiasbynens), [edg2s](https://github.com/edg2s), [dnkolegov](https://github.com/dnkolegov), [dhardtke](https://github.com/dhardtke), [wirehead](https://github.com/wirehead), [thorn0](https://github.com/thorn0), [styu](https://github.com/styu), [mozfreddyb](https://github.com/mozfreddyb), [mikesamuel](https://github.com/mikesamuel), [jorangreef](https://github.com/jorangreef), [jimmyhchan](https://github.com/jimmyhchan), [jameydeorio](https://github.com/jameydeorio), [jameskraus](https://github.com/jameskraus), [hyderali](https://github.com/hyderali), [hansottowirtz](https://github.com/hansottowirtz), [hackvertor](https://github.com/hackvertor), [freddyb](https://github.com/freddyb), [flavorjones](https://github.com/flavorjones), [djfarrelly](https://github.com/djfarrelly), [devd](https://github.com/devd), [camerondunford](https://github.com/camerondunford), [buu700](https://github.com/buu700), [buildog](https://github.com/buildog), [alabiaga](https://github.com/alabiaga), [Vector919](https://github.com/Vector919), [Robbert](https://github.com/Robbert), [GreLI](https://github.com/GreLI), [FuzzySockets](https://github.com/FuzzySockets), [ArtemBernatskyy](https://github.com/ArtemBernatskyy), [@garethheyes](https://twitter.com/garethheyes), [@shafigullin](https://twitter.com/shafigullin), [@mmrupp](https://twitter.com/mmrupp), [@irsdl](https://twitter.com/irsdl),[ShikariSenpai](https://github.com/ShikariSenpai), [ansjdnakjdnajkd](https://github.com/ansjdnakjdnajkd), [@asutherland](https://twitter.com/asutherland), [@mathias](https://twitter.com/mathias), [@cgvwzq](https://twitter.com/cgvwzq), [@robbertatwork](https://twitter.com/robbertatwork), [@giutro](https://twitter.com/giutro), [@CmdEngineer_](https://twitter.com/CmdEngineer_), [@avr4mit](https://twitter.com/avr4mit) and especially [@securitymb ❤️](https://twitter.com/securitymb) & [@masatokinugawa ❤️](https://twitter.com/masatokinugawa)
338
341
 
339
342
  ## Testing powered by
340
343
  <a target="_blank" href="https://www.browserstack.com/"><img width="200" src="https://www.browserstack.com/images/layout/browserstack-logo-600x315.png"></a><br>
@@ -1,4 +1,4 @@
1
- /*! @license DOMPurify | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.2.2/LICENSE */
1
+ /*! @license DOMPurify 2.3.1 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.3.1/LICENSE */
2
2
 
3
3
  'use strict';
4
4
 
@@ -168,7 +168,7 @@ var mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv
168
168
 
169
169
  var text = freeze(['#text']);
170
170
 
171
- var html$1 = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns']);
171
+ var html$1 = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns', 'slot']);
172
172
 
173
173
  var svg$1 = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'targetx', 'targety', 'transform', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);
174
174
 
@@ -245,7 +245,7 @@ function createDOMPurify() {
245
245
  * Version label, exposed for easier checks
246
246
  * if DOMPurify is up to date or not
247
247
  */
248
- DOMPurify.version = '2.2.7';
248
+ DOMPurify.version = '2.3.1';
249
249
 
250
250
  /**
251
251
  * Array of elements that DOMPurify removed during sanitation.
@@ -303,8 +303,8 @@ function createDOMPurify() {
303
303
  var _document = document,
304
304
  implementation = _document.implementation,
305
305
  createNodeIterator = _document.createNodeIterator,
306
- getElementsByTagName = _document.getElementsByTagName,
307
- createDocumentFragment = _document.createDocumentFragment;
306
+ createDocumentFragment = _document.createDocumentFragment,
307
+ getElementsByTagName = _document.getElementsByTagName;
308
308
  var importNode = originalDocument.importNode;
309
309
 
310
310
 
@@ -411,7 +411,8 @@ function createDOMPurify() {
411
411
  var USE_PROFILES = {};
412
412
 
413
413
  /* Tags to ignore content of when KEEP_CONTENT is true */
414
- var FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);
414
+ var FORBID_CONTENTS = null;
415
+ var DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);
415
416
 
416
417
  /* Tags that are safe for data: URIs */
417
418
  var DATA_URI_TAGS = null;
@@ -419,7 +420,14 @@ function createDOMPurify() {
419
420
 
420
421
  /* Attributes safe for values like "javascript:" */
421
422
  var URI_SAFE_ATTRIBUTES = null;
422
- var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'summary', 'title', 'value', 'style', 'xmlns']);
423
+ var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);
424
+
425
+ var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
426
+ var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
427
+ var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
428
+ /* Document namespace */
429
+ var NAMESPACE = HTML_NAMESPACE;
430
+ var IS_EMPTY_INPUT = false;
423
431
 
424
432
  /* Keep a reference to config to pass to hooks */
425
433
  var CONFIG = null;
@@ -453,6 +461,7 @@ function createDOMPurify() {
453
461
  ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
454
462
  URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR) : DEFAULT_URI_SAFE_ATTRIBUTES;
455
463
  DATA_URI_TAGS = 'ADD_DATA_URI_TAGS' in cfg ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS) : DEFAULT_DATA_URI_TAGS;
464
+ FORBID_CONTENTS = 'FORBID_CONTENTS' in cfg ? addToSet({}, cfg.FORBID_CONTENTS) : DEFAULT_FORBID_CONTENTS;
456
465
  FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};
457
466
  FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};
458
467
  USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
@@ -470,6 +479,7 @@ function createDOMPurify() {
470
479
  KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
471
480
  IN_PLACE = cfg.IN_PLACE || false; // Default false
472
481
  IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
482
+ NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
473
483
  if (SAFE_FOR_TEMPLATES) {
474
484
  ALLOW_DATA_ATTR = false;
475
485
  }
@@ -527,6 +537,14 @@ function createDOMPurify() {
527
537
  addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);
528
538
  }
529
539
 
540
+ if (cfg.FORBID_CONTENTS) {
541
+ if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
542
+ FORBID_CONTENTS = clone(FORBID_CONTENTS);
543
+ }
544
+
545
+ addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS);
546
+ }
547
+
530
548
  /* Add #text in case KEEP_CONTENT is set to true */
531
549
  if (KEEP_CONTENT) {
532
550
  ALLOWED_TAGS['#text'] = true;
@@ -566,10 +584,6 @@ function createDOMPurify() {
566
584
  var ALL_MATHML_TAGS = addToSet({}, mathMl);
567
585
  addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
568
586
 
569
- var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
570
- var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
571
- var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
572
-
573
587
  /**
574
588
  *
575
589
  *
@@ -669,6 +683,7 @@ function createDOMPurify() {
669
683
  var _forceRemove = function _forceRemove(node) {
670
684
  arrayPush(DOMPurify.removed, { element: node });
671
685
  try {
686
+ // eslint-disable-next-line unicorn/prefer-dom-node-remove
672
687
  node.parentNode.removeChild(node);
673
688
  } catch (_) {
674
689
  try {
@@ -734,27 +749,38 @@ function createDOMPurify() {
734
749
  }
735
750
 
736
751
  var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
737
- /* Use the DOMParser API by default, fallback later if needs be */
738
- try {
739
- doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
740
- } catch (_) {}
752
+ /*
753
+ * Use the DOMParser API by default, fallback later if needs be
754
+ * DOMParser not work for svg when has multiple root element.
755
+ */
756
+ if (NAMESPACE === HTML_NAMESPACE) {
757
+ try {
758
+ doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
759
+ } catch (_) {}
760
+ }
741
761
 
742
762
  /* Use createHTMLDocument in case DOMParser is not available */
743
763
  if (!doc || !doc.documentElement) {
744
- doc = implementation.createHTMLDocument('');
745
- var _doc = doc,
746
- body = _doc.body;
747
-
748
- body.parentNode.removeChild(body.parentNode.firstElementChild);
749
- body.outerHTML = dirtyPayload;
764
+ doc = implementation.createDocument(NAMESPACE, 'template', null);
765
+ try {
766
+ doc.documentElement.innerHTML = IS_EMPTY_INPUT ? '' : dirtyPayload;
767
+ } catch (_) {
768
+ // Syntax error if dirtyPayload is invalid xml
769
+ }
750
770
  }
751
771
 
772
+ var body = doc.body || doc.documentElement;
773
+
752
774
  if (dirty && leadingWhitespace) {
753
- doc.body.insertBefore(document.createTextNode(leadingWhitespace), doc.body.childNodes[0] || null);
775
+ body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
754
776
  }
755
777
 
756
778
  /* Work on whole document or just its body */
757
- return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
779
+ if (NAMESPACE === HTML_NAMESPACE) {
780
+ return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
781
+ }
782
+
783
+ return WHOLE_DOCUMENT ? doc.documentElement : body;
758
784
  };
759
785
 
760
786
  /**
@@ -764,9 +790,7 @@ function createDOMPurify() {
764
790
  * @return {Iterator} iterator instance
765
791
  */
766
792
  var _createIterator = function _createIterator(root) {
767
- return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, function () {
768
- return NodeFilter.FILTER_ACCEPT;
769
- }, false);
793
+ return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false);
770
794
  };
771
795
 
772
796
  /**
@@ -858,12 +882,18 @@ function createDOMPurify() {
858
882
  return true;
859
883
  }
860
884
 
885
+ /* Mitigate a problem with templates inside select */
886
+ if (tagName === 'select' && regExpTest(/<template/i, currentNode.innerHTML)) {
887
+ _forceRemove(currentNode);
888
+ return true;
889
+ }
890
+
861
891
  /* Remove element if anything forbids its presence */
862
892
  if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
863
893
  /* Keep content except for bad-listed elements */
864
894
  if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
865
- var parentNode = getParentNode(currentNode);
866
- var childNodes = getChildNodes(currentNode);
895
+ var parentNode = getParentNode(currentNode) || currentNode.parentNode;
896
+ var childNodes = getChildNodes(currentNode) || currentNode.childNodes;
867
897
 
868
898
  if (childNodes && parentNode) {
869
899
  var childCount = childNodes.length;
@@ -926,7 +956,7 @@ function createDOMPurify() {
926
956
  (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
927
957
  XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
928
958
  We don't need to check the value; it's always URI safe. */
929
- if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$$1, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$$1, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
959
+ if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$$1, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$$1, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
930
960
  return false;
931
961
 
932
962
  /* Check value is safe. First, is attr inert? If so, is safe */
@@ -1087,7 +1117,8 @@ function createDOMPurify() {
1087
1117
  /* Make sure we have a string to sanitize.
1088
1118
  DO NOT return early, as this will return the wrong type if
1089
1119
  the user has requested a DOM object rather than a string */
1090
- if (!dirty) {
1120
+ IS_EMPTY_INPUT = !dirty;
1121
+ if (IS_EMPTY_INPUT) {
1091
1122
  dirty = '<!-->';
1092
1123
  }
1093
1124
 
@@ -1143,7 +1174,7 @@ function createDOMPurify() {
1143
1174
  } else if (importedNode.nodeName === 'HTML') {
1144
1175
  body = importedNode;
1145
1176
  } else {
1146
- // eslint-disable-next-line unicorn/prefer-node-append
1177
+ // eslint-disable-next-line unicorn/prefer-dom-node-append
1147
1178
  body.appendChild(importedNode);
1148
1179
  }
1149
1180
  } else {
@@ -1207,7 +1238,7 @@ function createDOMPurify() {
1207
1238
  returnNode = createDocumentFragment.call(body.ownerDocument);
1208
1239
 
1209
1240
  while (body.firstChild) {
1210
- // eslint-disable-next-line unicorn/prefer-node-append
1241
+ // eslint-disable-next-line unicorn/prefer-dom-node-append
1211
1242
  returnNode.appendChild(body.firstChild);
1212
1243
  }
1213
1244
  } else {