dompurify 1.0.2 → 1.0.3

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
@@ -4,11 +4,11 @@
4
4
 
5
5
  DOMPurify is a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG.
6
6
 
7
- 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 1.0.2!
7
+ 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 1.0.3!
8
8
 
9
9
  DOMPurify is written in JavaScript and works in all modern browsers (Safari, 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.
10
10
 
11
- Our automated tests cover [16 different browsers](https://github.com/cure53/DOMPurify/blob/master/test/karma.conf.js#L163) right now, more to come. We also cover Node.js v4.0.0, v5.0.0 and v6.0.0, running DOMPurify on [jsdom](https://github.com/tmpvar/jsdom).
11
+ Our automated tests cover [16 different browsers](https://github.com/cure53/DOMPurify/blob/master/test/karma.custom-launchers.config.js#L5) right now, more to come. We also cover Node.js v4.0.0, v5.0.0 and v6.0.0, running DOMPurify on [jsdom](https://github.com/tmpvar/jsdom).
12
12
 
13
13
  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.
14
14
 
@@ -139,9 +139,14 @@ var clean = DOMPurify.sanitize(dirty, {ADD_ATTR: ['my-attr']});
139
139
  var clean = DOMPurify.sanitize(dirty, {ALLOW_DATA_ATTR: false});
140
140
 
141
141
  // allow external protocol handlers in URL attributes (default is false)
142
- // by default only http, https, ftp, ftps, tel and mailto are allowed.
142
+ // by default only http, https, ftp, ftps, tel, mailto, callto, cid and xmpp are allowed.
143
143
  var clean = DOMPurify.sanitize(dirty, {ALLOW_UNKNOWN_PROTOCOLS: true});
144
144
 
145
+ // allow specific protocols handlers in URL attributes (default is false)
146
+ // by default only http, https, ftp, ftps, tel, mailto, callto, cid and xmpp are allowed.
147
+ // Default RegExp: /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i;
148
+ var clean = DOMPurify.sanitize(dirty, {ALLOWED_URI_REGEXP: /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp|xxx):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i;});
149
+
145
150
  // return a DOM HTMLBodyElement instead of an HTML string (default is false)
146
151
  var clean = DOMPurify.sanitize(dirty, {RETURN_DOM: true});
147
152
 
@@ -11,7 +11,7 @@ var mathMl = ['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi',
11
11
 
12
12
  var text = ['#text'];
13
13
 
14
- var html$1 = ['accept', 'action', 'align', 'alt', 'autocomplete', 'background', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'coords', 'datetime', 'default', 'dir', 'disabled', 'download', 'enctype', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'ismap', 'label', 'lang', 'list', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'multiple', 'name', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'span', 'srclang', 'start', 'src', 'step', 'style', 'summary', 'tabindex', 'title', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns'];
14
+ var html$1 = ['accept', 'action', 'align', 'alt', 'autocomplete', 'background', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'coords', 'crossorigin', 'datetime', 'default', 'dir', 'disabled', 'download', 'enctype', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'integrity', 'ismap', 'label', 'lang', 'list', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'multiple', 'name', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', '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', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns'];
15
15
 
16
16
  var svg$1 = ['accent-height', 'accumulate', 'additivive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', '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', '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', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'specularconstant', 'specularexponent', 'spreadmethod', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'tabindex', 'targetx', 'targety', 'transform', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', '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'];
17
17
 
@@ -43,6 +43,14 @@ function clone(object) {
43
43
  return newObject;
44
44
  }
45
45
 
46
+ var MUSTACHE_EXPR = /\{\{[\s\S]*|[\s\S]*\}\}/gm; // Specify template detection regex for SAFE_FOR_TEMPLATES mode
47
+ var ERB_EXPR = /<%[\s\S]*|[\s\S]*%>/gm;
48
+ var DATA_ATTR = /^data-[\-\w.\u00B7-\uFFFF]/; // eslint-disable-line no-useless-escape
49
+ var ARIA_ATTR = /^aria-[\-\w]+$/; // eslint-disable-line no-useless-escape
50
+ var IS_ALLOWED_URI = /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i; // eslint-disable-line no-useless-escape
51
+ var IS_SCRIPT_OR_DATA = /^(?:\w+script|data):/i;
52
+ var ATTR_WHITESPACE = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g; // This needs to be extensive thanks to Webkit/Blink's behavior
53
+
46
54
  var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
47
55
 
48
56
  function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
@@ -59,15 +67,15 @@ function createDOMPurify() {
59
67
  };
60
68
 
61
69
  /**
62
- * Version label, exposed for easier checks
63
- * if DOMPurify is up to date or not
64
- */
65
- DOMPurify.version = '1.0.2';
70
+ * Version label, exposed for easier checks
71
+ * if DOMPurify is up to date or not
72
+ */
73
+ DOMPurify.version = '1.0.3';
66
74
 
67
75
  /**
68
- * Array of elements that DOMPurify removed during sanitation.
69
- * Empty if nothing was removed.
70
- */
76
+ * Array of elements that DOMPurify removed during sanitation.
77
+ * Empty if nothing was removed.
78
+ */
71
79
  DOMPurify.removed = [];
72
80
 
73
81
  if (!window || !window.document || window.document.nodeType !== 9) {
@@ -122,14 +130,23 @@ function createDOMPurify() {
122
130
  var hooks = {};
123
131
 
124
132
  /**
125
- * Expose whether this browser supports running the full DOMPurify.
126
- */
133
+ * Expose whether this browser supports running the full DOMPurify.
134
+ */
127
135
  DOMPurify.isSupported = implementation && typeof implementation.createHTMLDocument !== 'undefined' && document.documentMode !== 9;
128
136
 
137
+ var MUSTACHE_EXPR$$1 = MUSTACHE_EXPR,
138
+ ERB_EXPR$$1 = ERB_EXPR,
139
+ DATA_ATTR$$1 = DATA_ATTR,
140
+ ARIA_ATTR$$1 = ARIA_ATTR,
141
+ IS_SCRIPT_OR_DATA$$1 = IS_SCRIPT_OR_DATA,
142
+ ATTR_WHITESPACE$$1 = ATTR_WHITESPACE;
143
+
144
+
145
+ var IS_ALLOWED_URI$$1 = IS_ALLOWED_URI;
129
146
  /**
130
- * We consider the elements and attributes below to be safe. Ideally
131
- * don't add any new ones but feel free to remove unwanted ones.
132
- */
147
+ * We consider the elements and attributes below to be safe. Ideally
148
+ * don't add any new ones but feel free to remove unwanted ones.
149
+ */
133
150
 
134
151
  /* allowed element names */
135
152
  var ALLOWED_TAGS = null;
@@ -162,10 +179,6 @@ function createDOMPurify() {
162
179
  */
163
180
  var SAFE_FOR_TEMPLATES = false;
164
181
 
165
- /* Specify template detection regex for SAFE_FOR_TEMPLATES mode */
166
- var MUSTACHE_EXPR = /\{\{[\s\S]*|[\s\S]*\}\}/gm;
167
- var ERB_EXPR = /<%[\s\S]*|[\s\S]*%>/gm;
168
-
169
182
  /* Decide if document with <html>... should be returned */
170
183
  var WHOLE_DOCUMENT = false;
171
184
 
@@ -217,17 +230,16 @@ function createDOMPurify() {
217
230
  var formElement = document.createElement('form');
218
231
 
219
232
  /**
220
- * _parseConfig
221
- *
222
- * @param optional config literal
223
- */
233
+ * _parseConfig
234
+ *
235
+ * @param optional config literal
236
+ */
224
237
  // eslint-disable-next-line complexity
225
238
  var _parseConfig = function _parseConfig(cfg) {
226
239
  /* Shield configuration object from tampering */
227
240
  if ((typeof cfg === 'undefined' ? 'undefined' : _typeof(cfg)) !== 'object') {
228
241
  cfg = {};
229
242
  }
230
-
231
243
  /* Set configuration parameters */
232
244
  ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;
233
245
  ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
@@ -247,6 +259,8 @@ function createDOMPurify() {
247
259
  SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
248
260
  KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
249
261
 
262
+ IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
263
+
250
264
  if (SAFE_FOR_TEMPLATES) {
251
265
  ALLOW_DATA_ATTR = false;
252
266
  }
@@ -312,10 +326,10 @@ function createDOMPurify() {
312
326
  };
313
327
 
314
328
  /**
315
- * _forceRemove
316
- *
317
- * @param a DOM node
318
- */
329
+ * _forceRemove
330
+ *
331
+ * @param a DOM node
332
+ */
319
333
  var _forceRemove = function _forceRemove(node) {
320
334
  DOMPurify.removed.push({ element: node });
321
335
  try {
@@ -326,11 +340,11 @@ function createDOMPurify() {
326
340
  };
327
341
 
328
342
  /**
329
- * _removeAttribute
330
- *
331
- * @param an Attribute name
332
- * @param a DOM node
333
- */
343
+ * _removeAttribute
344
+ *
345
+ * @param an Attribute name
346
+ * @param a DOM node
347
+ */
334
348
  var _removeAttribute = function _removeAttribute(name, node) {
335
349
  DOMPurify.removed.push({
336
350
  attribute: node.getAttributeNode(name),
@@ -340,11 +354,11 @@ function createDOMPurify() {
340
354
  };
341
355
 
342
356
  /**
343
- * _initDocument
344
- *
345
- * @param a string of dirty markup
346
- * @return a DOM, filled with the dirty markup
347
- */
357
+ * _initDocument
358
+ *
359
+ * @param a string of dirty markup
360
+ * @return a DOM, filled with the dirty markup
361
+ */
348
362
  var _initDocument = function _initDocument(dirty) {
349
363
  /* Create a HTML document */
350
364
  var doc = void 0;
@@ -420,11 +434,11 @@ function createDOMPurify() {
420
434
  }
421
435
 
422
436
  /**
423
- * _createIterator
424
- *
425
- * @param document/fragment to create iterator for
426
- * @return iterator instance
427
- */
437
+ * _createIterator
438
+ *
439
+ * @param document/fragment to create iterator for
440
+ * @return iterator instance
441
+ */
428
442
  var _createIterator = function _createIterator(root) {
429
443
  return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, function () {
430
444
  return NodeFilter.FILTER_ACCEPT;
@@ -432,11 +446,11 @@ function createDOMPurify() {
432
446
  };
433
447
 
434
448
  /**
435
- * _isClobbered
436
- *
437
- * @param element to check for clobbering attacks
438
- * @return true if clobbered, false if safe
439
- */
449
+ * _isClobbered
450
+ *
451
+ * @param element to check for clobbering attacks
452
+ * @return true if clobbered, false if safe
453
+ */
440
454
  var _isClobbered = function _isClobbered(elm) {
441
455
  if (elm instanceof Text || elm instanceof Comment) {
442
456
  return false;
@@ -448,22 +462,22 @@ function createDOMPurify() {
448
462
  };
449
463
 
450
464
  /**
451
- * _isNode
452
- *
453
- * @param object to check whether it's a DOM node
454
- * @return true is object is a DOM node
455
- */
465
+ * _isNode
466
+ *
467
+ * @param object to check whether it's a DOM node
468
+ * @return true is object is a DOM node
469
+ */
456
470
  var _isNode = function _isNode(obj) {
457
471
  return (typeof Node === 'undefined' ? 'undefined' : _typeof(Node)) === 'object' ? obj instanceof Node : obj && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' && typeof obj.nodeType === 'number' && typeof obj.nodeName === 'string';
458
472
  };
459
473
 
460
474
  /**
461
- * _executeHook
462
- * Execute user configurable hooks
463
- *
464
- * @param {String} entryPoint Name of the hook's entry point
465
- * @param {Node} currentNode
466
- */
475
+ * _executeHook
476
+ * Execute user configurable hooks
477
+ *
478
+ * @param {String} entryPoint Name of the hook's entry point
479
+ * @param {Node} currentNode
480
+ */
467
481
  var _executeHook = function _executeHook(entryPoint, currentNode, data) {
468
482
  if (!hooks[entryPoint]) {
469
483
  return;
@@ -475,15 +489,15 @@ function createDOMPurify() {
475
489
  };
476
490
 
477
491
  /**
478
- * _sanitizeElements
479
- *
480
- * @protect nodeName
481
- * @protect textContent
482
- * @protect removeChild
483
- *
484
- * @param node to check for permission to exist
485
- * @return true if node was killed, false if left alive
486
- */
492
+ * _sanitizeElements
493
+ *
494
+ * @protect nodeName
495
+ * @protect textContent
496
+ * @protect removeChild
497
+ *
498
+ * @param node to check for permission to exist
499
+ * @return true if node was killed, false if left alive
500
+ */
487
501
  var _sanitizeElements = function _sanitizeElements(currentNode) {
488
502
  var content = void 0;
489
503
 
@@ -527,8 +541,8 @@ function createDOMPurify() {
527
541
  if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
528
542
  /* Get the element's text content */
529
543
  content = currentNode.textContent;
530
- content = content.replace(MUSTACHE_EXPR, ' ');
531
- content = content.replace(ERB_EXPR, ' ');
544
+ content = content.replace(MUSTACHE_EXPR$$1, ' ');
545
+ content = content.replace(ERB_EXPR$$1, ' ');
532
546
  if (currentNode.textContent !== content) {
533
547
  DOMPurify.removed.push({ element: currentNode.cloneNode() });
534
548
  currentNode.textContent = content;
@@ -541,24 +555,17 @@ function createDOMPurify() {
541
555
  return false;
542
556
  };
543
557
 
544
- var DATA_ATTR = /^data-[\-\w.\u00B7-\uFFFF]/; // eslint-disable-line no-useless-escape
545
- var ARIA_ATTR = /^aria-[\-\w]+$/; // eslint-disable-line no-useless-escape
546
- var IS_ALLOWED_URI = /^(?:(?:(?:f|ht)tps?|mailto|tel):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i; // eslint-disable-line no-useless-escape
547
- var IS_SCRIPT_OR_DATA = /^(?:\w+script|data):/i;
548
- /* This needs to be extensive thanks to Webkit/Blink's behavior */
549
- var ATTR_WHITESPACE = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g;
550
-
551
558
  /**
552
- * _sanitizeAttributes
553
- *
554
- * @protect attributes
555
- * @protect nodeName
556
- * @protect removeAttribute
557
- * @protect setAttribute
558
- *
559
- * @param node to sanitize
560
- * @return void
561
- */
559
+ * _sanitizeAttributes
560
+ *
561
+ * @protect attributes
562
+ * @protect nodeName
563
+ * @protect removeAttribute
564
+ * @protect setAttribute
565
+ *
566
+ * @param node to sanitize
567
+ * @return void
568
+ */
562
569
  // eslint-disable-next-line complexity
563
570
  var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
564
571
  var attr = void 0;
@@ -633,23 +640,23 @@ function createDOMPurify() {
633
640
  }
634
641
 
635
642
  /* Make sure attribute cannot clobber */
636
- if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in window || value in document || value in formElement)) {
643
+ if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
637
644
  continue;
638
645
  }
639
646
 
640
647
  /* Sanitize attribute content to be template-safe */
641
648
  if (SAFE_FOR_TEMPLATES) {
642
- value = value.replace(MUSTACHE_EXPR, ' ');
643
- value = value.replace(ERB_EXPR, ' ');
649
+ value = value.replace(MUSTACHE_EXPR$$1, ' ');
650
+ value = value.replace(ERB_EXPR$$1, ' ');
644
651
  }
645
652
 
646
653
  /* Allow valid data-* attributes: At least one character after "-"
647
654
  (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
648
655
  XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
649
656
  We don't need to check the value; it's always URI safe. */
650
- if (ALLOW_DATA_ATTR && DATA_ATTR.test(lcName)) {
657
+ if (ALLOW_DATA_ATTR && DATA_ATTR$$1.test(lcName)) {
651
658
  // This attribute is safe
652
- } else if (ALLOW_ARIA_ATTR && ARIA_ATTR.test(lcName)) {
659
+ } else if (ALLOW_ARIA_ATTR && ARIA_ATTR$$1.test(lcName)) {
653
660
  // This attribute is safe
654
661
  /* Otherwise, check the name is permitted */
655
662
  } else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
@@ -660,7 +667,7 @@ function createDOMPurify() {
660
667
  // This attribute is safe
661
668
  /* Check no script, data or unknown possibly unsafe URI
662
669
  unless we know URI values are safe for that attribute */
663
- } else if (IS_ALLOWED_URI.test(value.replace(ATTR_WHITESPACE, ''))) {
670
+ } else if (IS_ALLOWED_URI$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) {
664
671
  // This attribute is safe
665
672
  /* Keep image data URIs alive if src/xlink:href is allowed */
666
673
  } else if ((lcName === 'src' || lcName === 'xlink:href') && value.indexOf('data:') === 0 && DATA_URI_TAGS[currentNode.nodeName.toLowerCase()]) {
@@ -668,7 +675,7 @@ function createDOMPurify() {
668
675
  /* Allow unknown protocols: This provides support for links that
669
676
  are handled by protocol handlers which may be unknown ahead of
670
677
  time, e.g. fb:, spotify: */
671
- } else if (ALLOW_UNKNOWN_PROTOCOLS && !IS_SCRIPT_OR_DATA.test(value.replace(ATTR_WHITESPACE, ''))) {
678
+ } else if (ALLOW_UNKNOWN_PROTOCOLS && !IS_SCRIPT_OR_DATA$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) {
672
679
  // This attribute is safe
673
680
  /* Check for binary attributes */
674
681
  // eslint-disable-next-line no-negated-condition
@@ -691,11 +698,11 @@ function createDOMPurify() {
691
698
  };
692
699
 
693
700
  /**
694
- * _sanitizeShadowDOM
695
- *
696
- * @param fragment to iterate over recursively
697
- * @return void
698
- */
701
+ * _sanitizeShadowDOM
702
+ *
703
+ * @param fragment to iterate over recursively
704
+ * @return void
705
+ */
699
706
  var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
700
707
  var shadowNode = void 0;
701
708
  var shadowIterator = _createIterator(fragment);
@@ -726,12 +733,12 @@ function createDOMPurify() {
726
733
  };
727
734
 
728
735
  /**
729
- * Sanitize
730
- * Public method providing core sanitation functionality
731
- *
732
- * @param {String|Node} dirty string or DOM node
733
- * @param {Object} configuration object
734
- */
736
+ * Sanitize
737
+ * Public method providing core sanitation functionality
738
+ *
739
+ * @param {String|Node} dirty string or DOM node
740
+ * @param {Object} configuration object
741
+ */
735
742
  // eslint-disable-next-line complexity
736
743
  DOMPurify.sanitize = function (dirty, cfg) {
737
744
  var body = void 0;
@@ -753,6 +760,9 @@ function createDOMPurify() {
753
760
  throw new TypeError('toString is not a function');
754
761
  } else {
755
762
  dirty = dirty.toString();
763
+ if (typeof dirty !== 'string') {
764
+ throw new TypeError('dirty is not a string, aborting');
765
+ }
756
766
  }
757
767
  }
758
768
 
@@ -861,35 +871,35 @@ function createDOMPurify() {
861
871
  };
862
872
 
863
873
  /**
864
- * Public method to set the configuration once
865
- * setConfig
866
- *
867
- * @param {Object} configuration object
868
- * @return void
869
- */
874
+ * Public method to set the configuration once
875
+ * setConfig
876
+ *
877
+ * @param {Object} configuration object
878
+ * @return void
879
+ */
870
880
  DOMPurify.setConfig = function (cfg) {
871
881
  _parseConfig(cfg);
872
882
  SET_CONFIG = true;
873
883
  };
874
884
 
875
885
  /**
876
- * Public method to remove the configuration
877
- * clearConfig
878
- *
879
- * @return void
880
- */
886
+ * Public method to remove the configuration
887
+ * clearConfig
888
+ *
889
+ * @return void
890
+ */
881
891
  DOMPurify.clearConfig = function () {
882
892
  CONFIG = null;
883
893
  SET_CONFIG = false;
884
894
  };
885
895
 
886
896
  /**
887
- * AddHook
888
- * Public method to add DOMPurify hooks
889
- *
890
- * @param {String} entryPoint
891
- * @param {Function} hookFunction
892
- */
897
+ * AddHook
898
+ * Public method to add DOMPurify hooks
899
+ *
900
+ * @param {String} entryPoint
901
+ * @param {Function} hookFunction
902
+ */
893
903
  DOMPurify.addHook = function (entryPoint, hookFunction) {
894
904
  if (typeof hookFunction !== 'function') {
895
905
  return;
@@ -899,13 +909,13 @@ function createDOMPurify() {
899
909
  };
900
910
 
901
911
  /**
902
- * RemoveHook
903
- * Public method to remove a DOMPurify hook at a given entryPoint
904
- * (pops it from the stack of hooks if more are present)
905
- *
906
- * @param {String} entryPoint
907
- * @return void
908
- */
912
+ * RemoveHook
913
+ * Public method to remove a DOMPurify hook at a given entryPoint
914
+ * (pops it from the stack of hooks if more are present)
915
+ *
916
+ * @param {String} entryPoint
917
+ * @return void
918
+ */
909
919
  DOMPurify.removeHook = function (entryPoint) {
910
920
  if (hooks[entryPoint]) {
911
921
  hooks[entryPoint].pop();
@@ -913,12 +923,12 @@ function createDOMPurify() {
913
923
  };
914
924
 
915
925
  /**
916
- * RemoveHooks
917
- * Public method to remove all DOMPurify hooks at a given entryPoint
918
- *
919
- * @param {String} entryPoint
920
- * @return void
921
- */
926
+ * RemoveHooks
927
+ * Public method to remove all DOMPurify hooks at a given entryPoint
928
+ *
929
+ * @param {String} entryPoint
930
+ * @return void
931
+ */
922
932
  DOMPurify.removeHooks = function (entryPoint) {
923
933
  if (hooks[entryPoint]) {
924
934
  hooks[entryPoint] = [];
@@ -926,11 +936,11 @@ function createDOMPurify() {
926
936
  };
927
937
 
928
938
  /**
929
- * RemoveAllHooks
930
- * Public method to remove all DOMPurify hooks
931
- *
932
- * @return void
933
- */
939
+ * RemoveAllHooks
940
+ * Public method to remove all DOMPurify hooks
941
+ *
942
+ * @return void
943
+ */
934
944
  DOMPurify.removeAllHooks = function () {
935
945
  hooks = {};
936
946
  };