dompurify 2.0.15 → 2.1.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/dist/purify.es.js CHANGED
@@ -4,8 +4,7 @@ function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr
4
4
 
5
5
  var hasOwnProperty = Object.hasOwnProperty,
6
6
  setPrototypeOf = Object.setPrototypeOf,
7
- isFrozen = Object.isFrozen,
8
- objectKeys = Object.keys;
7
+ isFrozen = Object.isFrozen;
9
8
  var freeze = Object.freeze,
10
9
  seal = Object.seal,
11
10
  create = Object.create; // eslint-disable-line import/no-mutable-exports
@@ -39,11 +38,8 @@ if (!construct) {
39
38
  }
40
39
 
41
40
  var arrayForEach = unapply(Array.prototype.forEach);
42
- var arrayIndexOf = unapply(Array.prototype.indexOf);
43
- var arrayJoin = unapply(Array.prototype.join);
44
41
  var arrayPop = unapply(Array.prototype.pop);
45
42
  var arrayPush = unapply(Array.prototype.push);
46
- var arraySlice = unapply(Array.prototype.slice);
47
43
 
48
44
  var stringToLowerCase = unapply(String.prototype.toLowerCase);
49
45
  var stringMatch = unapply(String.prototype.match);
@@ -52,7 +48,6 @@ var stringIndexOf = unapply(String.prototype.indexOf);
52
48
  var stringTrim = unapply(String.prototype.trim);
53
49
 
54
50
  var regExpTest = unapply(RegExp.prototype.test);
55
- var regExpCreate = unconstruct(RegExp);
56
51
 
57
52
  var typeErrorCreate = unconstruct(TypeError);
58
53
 
@@ -208,7 +203,7 @@ function createDOMPurify() {
208
203
  * Version label, exposed for easier checks
209
204
  * if DOMPurify is up to date or not
210
205
  */
211
- DOMPurify.version = '2.0.15';
206
+ DOMPurify.version = '2.1.1';
212
207
 
213
208
  /**
214
209
  * Array of elements that DOMPurify removed during sanitation.
@@ -225,7 +220,6 @@ function createDOMPurify() {
225
220
  }
226
221
 
227
222
  var originalDocument = window.document;
228
- var removeTitle = false;
229
223
 
230
224
  var document = window.document;
231
225
  var DocumentFragment = window.DocumentFragment,
@@ -264,7 +258,10 @@ function createDOMPurify() {
264
258
  var importNode = originalDocument.importNode;
265
259
 
266
260
 
267
- var documentMode = clone(document).documentMode ? document.documentMode : {};
261
+ var documentMode = {};
262
+ try {
263
+ documentMode = clone(document).documentMode ? document.documentMode : {};
264
+ } catch (_) {}
268
265
 
269
266
  var hooks = {};
270
267
 
@@ -310,9 +307,6 @@ function createDOMPurify() {
310
307
  /* Decide if unknown protocols are okay */
311
308
  var ALLOW_UNKNOWN_PROTOCOLS = false;
312
309
 
313
- /* Output should be safe for jQuery's $() factory? */
314
- var SAFE_FOR_JQUERY = false;
315
-
316
310
  /* Output should be safe for common template engines.
317
311
  * This means, DOMPurify removes data attributes, mustaches and ERB
318
312
  */
@@ -410,7 +404,6 @@ function createDOMPurify() {
410
404
  ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
411
405
  ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
412
406
  ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
413
- SAFE_FOR_JQUERY = cfg.SAFE_FOR_JQUERY || false; // Default false
414
407
  SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false
415
408
  WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
416
409
  RETURN_DOM = cfg.RETURN_DOM || false; // Default false
@@ -565,11 +558,6 @@ function createDOMPurify() {
565
558
  doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
566
559
  } catch (_) {}
567
560
 
568
- /* Remove title to fix a mXSS bug in older MS Edge */
569
- if (removeTitle) {
570
- addToSet(FORBID_TAGS, ['title']);
571
- }
572
-
573
561
  /* Use createHTMLDocument in case DOMParser is not available */
574
562
  if (!doc || !doc.documentElement) {
575
563
  doc = implementation.createHTMLDocument('');
@@ -588,18 +576,6 @@ function createDOMPurify() {
588
576
  return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
589
577
  };
590
578
 
591
- /* Here we test for a broken feature in Edge that might cause mXSS */
592
- if (DOMPurify.isSupported) {
593
- (function () {
594
- try {
595
- var doc = _initDocument('<x/><title>&lt;/title&gt;&lt;img&gt;');
596
- if (regExpTest(/<\/title/, doc.querySelector('title').innerHTML)) {
597
- removeTitle = true;
598
- }
599
- } catch (_) {}
600
- })();
601
- }
602
-
603
579
  /**
604
580
  * _createIterator
605
581
  *
@@ -668,7 +644,6 @@ function createDOMPurify() {
668
644
  * @param {Node} currentNode to check for permission to exist
669
645
  * @return {Boolean} true if node was killed, false if left alive
670
646
  */
671
- // eslint-disable-next-line complexity
672
647
  var _sanitizeElements = function _sanitizeElements(currentNode) {
673
648
  var content = void 0;
674
649
 
@@ -702,6 +677,12 @@ function createDOMPurify() {
702
677
  return true;
703
678
  }
704
679
 
680
+ /* Detect mXSS attempts abusing namespace confusion */
681
+ if (!_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/<[!/\w]/g, currentNode.innerHTML) && regExpTest(/<[!/\w]/g, currentNode.textContent)) {
682
+ _forceRemove(currentNode);
683
+ return true;
684
+ }
685
+
705
686
  /* Remove element if anything forbids its presence */
706
687
  if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
707
688
  /* Keep content except for bad-listed elements */
@@ -717,26 +698,11 @@ function createDOMPurify() {
717
698
  }
718
699
 
719
700
  /* Remove in case a noscript/noembed XSS is suspected */
720
- if (tagName === 'noscript' && regExpTest(/<\/noscript/i, currentNode.innerHTML)) {
721
- _forceRemove(currentNode);
722
- return true;
723
- }
724
-
725
- if (tagName === 'noembed' && regExpTest(/<\/noembed/i, currentNode.innerHTML)) {
701
+ if ((tagName === 'noscript' || tagName === 'noembed') && regExpTest(/<\/no(script|embed)/i, currentNode.innerHTML)) {
726
702
  _forceRemove(currentNode);
727
703
  return true;
728
704
  }
729
705
 
730
- /* Convert markup to cover jQuery behavior */
731
- if (SAFE_FOR_JQUERY && !_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/</g, currentNode.textContent)) {
732
- arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
733
- if (currentNode.innerHTML) {
734
- currentNode.innerHTML = stringReplace(currentNode.innerHTML, /</g, '&lt;');
735
- } else {
736
- currentNode.innerHTML = stringReplace(currentNode.textContent, /</g, '&lt;');
737
- }
738
- }
739
-
740
706
  /* Sanitize element content to be template-safe */
741
707
  if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
742
708
  /* Get the element's text content */
@@ -795,12 +761,10 @@ function createDOMPurify() {
795
761
  *
796
762
  * @param {Node} currentNode to sanitize
797
763
  */
798
- // eslint-disable-next-line complexity
799
764
  var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
800
765
  var attr = void 0;
801
766
  var value = void 0;
802
767
  var lcName = void 0;
803
- var idAttr = void 0;
804
768
  var l = void 0;
805
769
  /* Execute a hook if present */
806
770
  _executeHook('beforeSanitizeAttributes', currentNode, null);
@@ -844,32 +808,7 @@ function createDOMPurify() {
844
808
  }
845
809
 
846
810
  /* Remove attribute */
847
- // Safari (iOS + Mac), last tested v8.0.5, crashes if you try to
848
- // remove a "name" attribute from an <img> tag that has an "id"
849
- // attribute at the time.
850
- if (lcName === 'name' && currentNode.nodeName === 'IMG' && attributes.id) {
851
- idAttr = attributes.id;
852
- attributes = arraySlice(attributes, []);
853
- _removeAttribute('id', currentNode);
854
- _removeAttribute(name, currentNode);
855
- if (arrayIndexOf(attributes, idAttr) > l) {
856
- currentNode.setAttribute('id', idAttr.value);
857
- }
858
- } else if (
859
- // This works around a bug in Safari, where input[type=file]
860
- // cannot be dynamically set after type has been removed
861
- currentNode.nodeName === 'INPUT' && lcName === 'type' && value === 'file' && hookEvent.keepAttr && (ALLOWED_ATTR[lcName] || !FORBID_ATTR[lcName])) {
862
- continue;
863
- } else {
864
- // This avoids a crash in Safari v9.0 with double-ids.
865
- // The trick is to first set the id to be empty and then to
866
- // remove the attribute
867
- if (name === 'id') {
868
- currentNode.setAttribute(name, '');
869
- }
870
-
871
- _removeAttribute(name, currentNode);
872
- }
811
+ _removeAttribute(name, currentNode);
873
812
 
874
813
  /* Did the hooks approve of the attribute? */
875
814
  if (!hookEvent.keepAttr) {
@@ -877,13 +816,7 @@ function createDOMPurify() {
877
816
  }
878
817
 
879
818
  /* Work around a security issue in jQuery 3.0 */
880
- if (SAFE_FOR_JQUERY && regExpTest(/\/>/i, value)) {
881
- _removeAttribute(name, currentNode);
882
- continue;
883
- }
884
-
885
- /* Take care of an mXSS pattern using namespace switches */
886
- if (regExpTest(/svg|math/i, currentNode.namespaceURI) && regExpTest(regExpCreate('</(' + arrayJoin(objectKeys(FORBID_CONTENTS), '|') + ')', 'i'), value)) {
819
+ if (regExpTest(/\/>/i, value)) {
887
820
  _removeAttribute(name, currentNode);
888
821
  continue;
889
822
  }
@@ -1016,7 +949,7 @@ function createDOMPurify() {
1016
949
  if (IN_PLACE) ; else if (dirty instanceof Node) {
1017
950
  /* If dirty is a DOM element, append to an empty document to avoid
1018
951
  elements being stripped by the parser */
1019
- body = _initDocument('<!-->');
952
+ body = _initDocument('<!---->');
1020
953
  importedNode = body.ownerDocument.importNode(dirty, true);
1021
954
  if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {
1022
955
  /* Node is already a body, use as is */