dompurify 2.2.6 → 2.3.0

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.6.
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.0.
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
 
@@ -160,6 +160,8 @@ var clean = DOMPurify.sanitize(dirty, {ALLOWED_TAGS: ['b']});
160
160
  var clean = DOMPurify.sanitize(dirty, {ALLOWED_TAGS: ['b', 'q'], ALLOWED_ATTR: ['style']});
161
161
 
162
162
  // allow all safe HTML elements but neither SVG nor MathML
163
+ // note that the USE_PROFILES setting will override the ALLOWED_TAGS setting
164
+ // so don't use them together
163
165
  var clean = DOMPurify.sanitize(dirty, {USE_PROFILES: {html: true}});
164
166
 
165
167
  // allow all safe SVG elements and SVG Filters, no HTML or MathML
@@ -168,6 +170,9 @@ var clean = DOMPurify.sanitize(dirty, {USE_PROFILES: {svg: true, svgFilters: tru
168
170
  // allow all safe MathML elements and SVG, but no SVG Filters
169
171
  var clean = DOMPurify.sanitize(dirty, {USE_PROFILES: {mathMl: true, svg: true}});
170
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
+
171
176
  // leave all safe HTML as it is and add <style> elements to block-list
172
177
  var clean = DOMPurify.sanitize(dirty, {FORBID_TAGS: ['style']});
173
178
 
@@ -332,7 +337,7 @@ Feature releases will not be announced to this list.
332
337
 
333
338
  Many people helped and help DOMPurify become what it is and need to be acknowledged here!
334
339
 
335
- [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) 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)
336
341
 
337
342
  ## Testing powered by
338
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.0 | (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.0/LICENSE */
2
2
 
3
3
  'use strict';
4
4
 
@@ -139,7 +139,12 @@ function lookupGetter(object, prop) {
139
139
  object = getPrototypeOf(object);
140
140
  }
141
141
 
142
- return null;
142
+ function fallbackValue(element) {
143
+ console.warn('fallback value for', element);
144
+ return null;
145
+ }
146
+
147
+ return fallbackValue;
143
148
  }
144
149
 
145
150
  var html = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);
@@ -163,7 +168,7 @@ var mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv
163
168
 
164
169
  var text = freeze(['#text']);
165
170
 
166
- 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']);
167
172
 
168
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']);
169
174
 
@@ -240,7 +245,7 @@ function createDOMPurify() {
240
245
  * Version label, exposed for easier checks
241
246
  * if DOMPurify is up to date or not
242
247
  */
243
- DOMPurify.version = '2.2.6';
248
+ DOMPurify.version = '2.3.0';
244
249
 
245
250
  /**
246
251
  * Array of elements that DOMPurify removed during sanitation.
@@ -298,8 +303,8 @@ function createDOMPurify() {
298
303
  var _document = document,
299
304
  implementation = _document.implementation,
300
305
  createNodeIterator = _document.createNodeIterator,
301
- getElementsByTagName = _document.getElementsByTagName,
302
- createDocumentFragment = _document.createDocumentFragment;
306
+ createDocumentFragment = _document.createDocumentFragment,
307
+ getElementsByTagName = _document.getElementsByTagName;
303
308
  var importNode = originalDocument.importNode;
304
309
 
305
310
 
@@ -313,7 +318,7 @@ function createDOMPurify() {
313
318
  /**
314
319
  * Expose whether this browser supports running the full DOMPurify.
315
320
  */
316
- DOMPurify.isSupported = implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;
321
+ DOMPurify.isSupported = typeof getParentNode === 'function' && implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;
317
322
 
318
323
  var MUSTACHE_EXPR$$1 = MUSTACHE_EXPR,
319
324
  ERB_EXPR$$1 = ERB_EXPR,
@@ -416,6 +421,13 @@ function createDOMPurify() {
416
421
  var URI_SAFE_ATTRIBUTES = null;
417
422
  var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'summary', 'title', 'value', 'style', 'xmlns']);
418
423
 
424
+ var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
425
+ var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
426
+ var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
427
+ /* Document namespace */
428
+ var NAMESPACE = HTML_NAMESPACE;
429
+ var IS_EMPTY_INPUT = false;
430
+
419
431
  /* Keep a reference to config to pass to hooks */
420
432
  var CONFIG = null;
421
433
 
@@ -465,6 +477,7 @@ function createDOMPurify() {
465
477
  KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
466
478
  IN_PLACE = cfg.IN_PLACE || false; // Default false
467
479
  IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
480
+ NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
468
481
  if (SAFE_FOR_TEMPLATES) {
469
482
  ALLOW_DATA_ATTR = false;
470
483
  }
@@ -561,10 +574,6 @@ function createDOMPurify() {
561
574
  var ALL_MATHML_TAGS = addToSet({}, mathMl);
562
575
  addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
563
576
 
564
- var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
565
- var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
566
- var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
567
-
568
577
  /**
569
578
  *
570
579
  *
@@ -664,6 +673,7 @@ function createDOMPurify() {
664
673
  var _forceRemove = function _forceRemove(node) {
665
674
  arrayPush(DOMPurify.removed, { element: node });
666
675
  try {
676
+ // eslint-disable-next-line unicorn/prefer-dom-node-remove
667
677
  node.parentNode.removeChild(node);
668
678
  } catch (_) {
669
679
  try {
@@ -694,6 +704,19 @@ function createDOMPurify() {
694
704
  }
695
705
 
696
706
  node.removeAttribute(name);
707
+
708
+ // We void attribute values for unremovable "is"" attributes
709
+ if (name === 'is' && !ALLOWED_ATTR[name]) {
710
+ if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
711
+ try {
712
+ _forceRemove(node);
713
+ } catch (_) {}
714
+ } else {
715
+ try {
716
+ node.setAttribute(name, '');
717
+ } catch (_) {}
718
+ }
719
+ }
697
720
  };
698
721
 
699
722
  /**
@@ -716,27 +739,38 @@ function createDOMPurify() {
716
739
  }
717
740
 
718
741
  var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
719
- /* Use the DOMParser API by default, fallback later if needs be */
720
- try {
721
- doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
722
- } catch (_) {}
742
+ /*
743
+ * Use the DOMParser API by default, fallback later if needs be
744
+ * DOMParser not work for svg when has multiple root element.
745
+ */
746
+ if (NAMESPACE === HTML_NAMESPACE) {
747
+ try {
748
+ doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
749
+ } catch (_) {}
750
+ }
723
751
 
724
752
  /* Use createHTMLDocument in case DOMParser is not available */
725
753
  if (!doc || !doc.documentElement) {
726
- doc = implementation.createHTMLDocument('');
727
- var _doc = doc,
728
- body = _doc.body;
729
-
730
- body.parentNode.removeChild(body.parentNode.firstElementChild);
731
- body.outerHTML = dirtyPayload;
754
+ doc = implementation.createDocument(NAMESPACE, 'template', null);
755
+ try {
756
+ doc.documentElement.innerHTML = IS_EMPTY_INPUT ? '' : dirtyPayload;
757
+ } catch (_) {
758
+ // Syntax error if dirtyPayload is invalid xml
759
+ }
732
760
  }
733
761
 
762
+ var body = doc.body || doc.documentElement;
763
+
734
764
  if (dirty && leadingWhitespace) {
735
- doc.body.insertBefore(document.createTextNode(leadingWhitespace), doc.body.childNodes[0] || null);
765
+ body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
736
766
  }
737
767
 
738
768
  /* Work on whole document or just its body */
739
- return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
769
+ if (NAMESPACE === HTML_NAMESPACE) {
770
+ return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
771
+ }
772
+
773
+ return WHOLE_DOCUMENT ? doc.documentElement : body;
740
774
  };
741
775
 
742
776
  /**
@@ -746,9 +780,7 @@ function createDOMPurify() {
746
780
  * @return {Iterator} iterator instance
747
781
  */
748
782
  var _createIterator = function _createIterator(root) {
749
- return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, function () {
750
- return NodeFilter.FILTER_ACCEPT;
751
- }, false);
783
+ return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false);
752
784
  };
753
785
 
754
786
  /**
@@ -844,11 +876,15 @@ function createDOMPurify() {
844
876
  if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
845
877
  /* Keep content except for bad-listed elements */
846
878
  if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
847
- var parentNode = getParentNode(currentNode);
848
- var childNodes = getChildNodes(currentNode);
849
- var childCount = childNodes.length;
850
- for (var i = childCount - 1; i >= 0; --i) {
851
- parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));
879
+ var parentNode = getParentNode(currentNode) || currentNode.parentNode;
880
+ var childNodes = getChildNodes(currentNode) || currentNode.childNodes;
881
+
882
+ if (childNodes && parentNode) {
883
+ var childCount = childNodes.length;
884
+
885
+ for (var i = childCount - 1; i >= 0; --i) {
886
+ parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));
887
+ }
852
888
  }
853
889
  }
854
890
 
@@ -904,7 +940,7 @@ function createDOMPurify() {
904
940
  (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
905
941
  XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
906
942
  We don't need to check the value; it's always URI safe. */
907
- 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]) {
943
+ 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]) {
908
944
  return false;
909
945
 
910
946
  /* Check value is safe. First, is attr inert? If so, is safe */
@@ -1065,7 +1101,8 @@ function createDOMPurify() {
1065
1101
  /* Make sure we have a string to sanitize.
1066
1102
  DO NOT return early, as this will return the wrong type if
1067
1103
  the user has requested a DOM object rather than a string */
1068
- if (!dirty) {
1104
+ IS_EMPTY_INPUT = !dirty;
1105
+ if (IS_EMPTY_INPUT) {
1069
1106
  dirty = '<!-->';
1070
1107
  }
1071
1108
 
@@ -1121,7 +1158,7 @@ function createDOMPurify() {
1121
1158
  } else if (importedNode.nodeName === 'HTML') {
1122
1159
  body = importedNode;
1123
1160
  } else {
1124
- // eslint-disable-next-line unicorn/prefer-node-append
1161
+ // eslint-disable-next-line unicorn/prefer-dom-node-append
1125
1162
  body.appendChild(importedNode);
1126
1163
  }
1127
1164
  } else {
@@ -1185,7 +1222,7 @@ function createDOMPurify() {
1185
1222
  returnNode = createDocumentFragment.call(body.ownerDocument);
1186
1223
 
1187
1224
  while (body.firstChild) {
1188
- // eslint-disable-next-line unicorn/prefer-node-append
1225
+ // eslint-disable-next-line unicorn/prefer-dom-node-append
1189
1226
  returnNode.appendChild(body.firstChild);
1190
1227
  }
1191
1228
  } else {