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/README.md +6 -8
- package/dist/purify.cjs.js +16 -83
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.js +16 -83
- package/dist/purify.es.js.map +1 -1
- package/dist/purify.js +16 -83
- package/dist/purify.js.map +1 -1
- package/dist/purify.min.js +1 -1
- package/dist/purify.min.js.map +1 -1
- package/package.json +1 -1
package/dist/purify.js
CHANGED
|
@@ -10,8 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
var hasOwnProperty = Object.hasOwnProperty,
|
|
12
12
|
setPrototypeOf = Object.setPrototypeOf,
|
|
13
|
-
isFrozen = Object.isFrozen
|
|
14
|
-
objectKeys = Object.keys;
|
|
13
|
+
isFrozen = Object.isFrozen;
|
|
15
14
|
var freeze = Object.freeze,
|
|
16
15
|
seal = Object.seal,
|
|
17
16
|
create = Object.create; // eslint-disable-line import/no-mutable-exports
|
|
@@ -45,11 +44,8 @@
|
|
|
45
44
|
}
|
|
46
45
|
|
|
47
46
|
var arrayForEach = unapply(Array.prototype.forEach);
|
|
48
|
-
var arrayIndexOf = unapply(Array.prototype.indexOf);
|
|
49
|
-
var arrayJoin = unapply(Array.prototype.join);
|
|
50
47
|
var arrayPop = unapply(Array.prototype.pop);
|
|
51
48
|
var arrayPush = unapply(Array.prototype.push);
|
|
52
|
-
var arraySlice = unapply(Array.prototype.slice);
|
|
53
49
|
|
|
54
50
|
var stringToLowerCase = unapply(String.prototype.toLowerCase);
|
|
55
51
|
var stringMatch = unapply(String.prototype.match);
|
|
@@ -58,7 +54,6 @@
|
|
|
58
54
|
var stringTrim = unapply(String.prototype.trim);
|
|
59
55
|
|
|
60
56
|
var regExpTest = unapply(RegExp.prototype.test);
|
|
61
|
-
var regExpCreate = unconstruct(RegExp);
|
|
62
57
|
|
|
63
58
|
var typeErrorCreate = unconstruct(TypeError);
|
|
64
59
|
|
|
@@ -214,7 +209,7 @@
|
|
|
214
209
|
* Version label, exposed for easier checks
|
|
215
210
|
* if DOMPurify is up to date or not
|
|
216
211
|
*/
|
|
217
|
-
DOMPurify.version = '2.
|
|
212
|
+
DOMPurify.version = '2.1.1';
|
|
218
213
|
|
|
219
214
|
/**
|
|
220
215
|
* Array of elements that DOMPurify removed during sanitation.
|
|
@@ -231,7 +226,6 @@
|
|
|
231
226
|
}
|
|
232
227
|
|
|
233
228
|
var originalDocument = window.document;
|
|
234
|
-
var removeTitle = false;
|
|
235
229
|
|
|
236
230
|
var document = window.document;
|
|
237
231
|
var DocumentFragment = window.DocumentFragment,
|
|
@@ -270,7 +264,10 @@
|
|
|
270
264
|
var importNode = originalDocument.importNode;
|
|
271
265
|
|
|
272
266
|
|
|
273
|
-
var documentMode =
|
|
267
|
+
var documentMode = {};
|
|
268
|
+
try {
|
|
269
|
+
documentMode = clone(document).documentMode ? document.documentMode : {};
|
|
270
|
+
} catch (_) {}
|
|
274
271
|
|
|
275
272
|
var hooks = {};
|
|
276
273
|
|
|
@@ -316,9 +313,6 @@
|
|
|
316
313
|
/* Decide if unknown protocols are okay */
|
|
317
314
|
var ALLOW_UNKNOWN_PROTOCOLS = false;
|
|
318
315
|
|
|
319
|
-
/* Output should be safe for jQuery's $() factory? */
|
|
320
|
-
var SAFE_FOR_JQUERY = false;
|
|
321
|
-
|
|
322
316
|
/* Output should be safe for common template engines.
|
|
323
317
|
* This means, DOMPurify removes data attributes, mustaches and ERB
|
|
324
318
|
*/
|
|
@@ -416,7 +410,6 @@
|
|
|
416
410
|
ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
|
|
417
411
|
ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
|
|
418
412
|
ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
|
|
419
|
-
SAFE_FOR_JQUERY = cfg.SAFE_FOR_JQUERY || false; // Default false
|
|
420
413
|
SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false
|
|
421
414
|
WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
|
|
422
415
|
RETURN_DOM = cfg.RETURN_DOM || false; // Default false
|
|
@@ -571,11 +564,6 @@
|
|
|
571
564
|
doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
|
|
572
565
|
} catch (_) {}
|
|
573
566
|
|
|
574
|
-
/* Remove title to fix a mXSS bug in older MS Edge */
|
|
575
|
-
if (removeTitle) {
|
|
576
|
-
addToSet(FORBID_TAGS, ['title']);
|
|
577
|
-
}
|
|
578
|
-
|
|
579
567
|
/* Use createHTMLDocument in case DOMParser is not available */
|
|
580
568
|
if (!doc || !doc.documentElement) {
|
|
581
569
|
doc = implementation.createHTMLDocument('');
|
|
@@ -594,18 +582,6 @@
|
|
|
594
582
|
return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
|
|
595
583
|
};
|
|
596
584
|
|
|
597
|
-
/* Here we test for a broken feature in Edge that might cause mXSS */
|
|
598
|
-
if (DOMPurify.isSupported) {
|
|
599
|
-
(function () {
|
|
600
|
-
try {
|
|
601
|
-
var doc = _initDocument('<x/><title></title><img>');
|
|
602
|
-
if (regExpTest(/<\/title/, doc.querySelector('title').innerHTML)) {
|
|
603
|
-
removeTitle = true;
|
|
604
|
-
}
|
|
605
|
-
} catch (_) {}
|
|
606
|
-
})();
|
|
607
|
-
}
|
|
608
|
-
|
|
609
585
|
/**
|
|
610
586
|
* _createIterator
|
|
611
587
|
*
|
|
@@ -674,7 +650,6 @@
|
|
|
674
650
|
* @param {Node} currentNode to check for permission to exist
|
|
675
651
|
* @return {Boolean} true if node was killed, false if left alive
|
|
676
652
|
*/
|
|
677
|
-
// eslint-disable-next-line complexity
|
|
678
653
|
var _sanitizeElements = function _sanitizeElements(currentNode) {
|
|
679
654
|
var content = void 0;
|
|
680
655
|
|
|
@@ -708,6 +683,12 @@
|
|
|
708
683
|
return true;
|
|
709
684
|
}
|
|
710
685
|
|
|
686
|
+
/* Detect mXSS attempts abusing namespace confusion */
|
|
687
|
+
if (!_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/<[!/\w]/g, currentNode.innerHTML) && regExpTest(/<[!/\w]/g, currentNode.textContent)) {
|
|
688
|
+
_forceRemove(currentNode);
|
|
689
|
+
return true;
|
|
690
|
+
}
|
|
691
|
+
|
|
711
692
|
/* Remove element if anything forbids its presence */
|
|
712
693
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
713
694
|
/* Keep content except for bad-listed elements */
|
|
@@ -723,26 +704,11 @@
|
|
|
723
704
|
}
|
|
724
705
|
|
|
725
706
|
/* Remove in case a noscript/noembed XSS is suspected */
|
|
726
|
-
if (tagName === 'noscript' && regExpTest(/<\/
|
|
727
|
-
_forceRemove(currentNode);
|
|
728
|
-
return true;
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
if (tagName === 'noembed' && regExpTest(/<\/noembed/i, currentNode.innerHTML)) {
|
|
707
|
+
if ((tagName === 'noscript' || tagName === 'noembed') && regExpTest(/<\/no(script|embed)/i, currentNode.innerHTML)) {
|
|
732
708
|
_forceRemove(currentNode);
|
|
733
709
|
return true;
|
|
734
710
|
}
|
|
735
711
|
|
|
736
|
-
/* Convert markup to cover jQuery behavior */
|
|
737
|
-
if (SAFE_FOR_JQUERY && !_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/</g, currentNode.textContent)) {
|
|
738
|
-
arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
|
|
739
|
-
if (currentNode.innerHTML) {
|
|
740
|
-
currentNode.innerHTML = stringReplace(currentNode.innerHTML, /</g, '<');
|
|
741
|
-
} else {
|
|
742
|
-
currentNode.innerHTML = stringReplace(currentNode.textContent, /</g, '<');
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
|
|
746
712
|
/* Sanitize element content to be template-safe */
|
|
747
713
|
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
|
|
748
714
|
/* Get the element's text content */
|
|
@@ -801,12 +767,10 @@
|
|
|
801
767
|
*
|
|
802
768
|
* @param {Node} currentNode to sanitize
|
|
803
769
|
*/
|
|
804
|
-
// eslint-disable-next-line complexity
|
|
805
770
|
var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
|
|
806
771
|
var attr = void 0;
|
|
807
772
|
var value = void 0;
|
|
808
773
|
var lcName = void 0;
|
|
809
|
-
var idAttr = void 0;
|
|
810
774
|
var l = void 0;
|
|
811
775
|
/* Execute a hook if present */
|
|
812
776
|
_executeHook('beforeSanitizeAttributes', currentNode, null);
|
|
@@ -850,32 +814,7 @@
|
|
|
850
814
|
}
|
|
851
815
|
|
|
852
816
|
/* Remove attribute */
|
|
853
|
-
|
|
854
|
-
// remove a "name" attribute from an <img> tag that has an "id"
|
|
855
|
-
// attribute at the time.
|
|
856
|
-
if (lcName === 'name' && currentNode.nodeName === 'IMG' && attributes.id) {
|
|
857
|
-
idAttr = attributes.id;
|
|
858
|
-
attributes = arraySlice(attributes, []);
|
|
859
|
-
_removeAttribute('id', currentNode);
|
|
860
|
-
_removeAttribute(name, currentNode);
|
|
861
|
-
if (arrayIndexOf(attributes, idAttr) > l) {
|
|
862
|
-
currentNode.setAttribute('id', idAttr.value);
|
|
863
|
-
}
|
|
864
|
-
} else if (
|
|
865
|
-
// This works around a bug in Safari, where input[type=file]
|
|
866
|
-
// cannot be dynamically set after type has been removed
|
|
867
|
-
currentNode.nodeName === 'INPUT' && lcName === 'type' && value === 'file' && hookEvent.keepAttr && (ALLOWED_ATTR[lcName] || !FORBID_ATTR[lcName])) {
|
|
868
|
-
continue;
|
|
869
|
-
} else {
|
|
870
|
-
// This avoids a crash in Safari v9.0 with double-ids.
|
|
871
|
-
// The trick is to first set the id to be empty and then to
|
|
872
|
-
// remove the attribute
|
|
873
|
-
if (name === 'id') {
|
|
874
|
-
currentNode.setAttribute(name, '');
|
|
875
|
-
}
|
|
876
|
-
|
|
877
|
-
_removeAttribute(name, currentNode);
|
|
878
|
-
}
|
|
817
|
+
_removeAttribute(name, currentNode);
|
|
879
818
|
|
|
880
819
|
/* Did the hooks approve of the attribute? */
|
|
881
820
|
if (!hookEvent.keepAttr) {
|
|
@@ -883,13 +822,7 @@
|
|
|
883
822
|
}
|
|
884
823
|
|
|
885
824
|
/* Work around a security issue in jQuery 3.0 */
|
|
886
|
-
if (
|
|
887
|
-
_removeAttribute(name, currentNode);
|
|
888
|
-
continue;
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
/* Take care of an mXSS pattern using namespace switches */
|
|
892
|
-
if (regExpTest(/svg|math/i, currentNode.namespaceURI) && regExpTest(regExpCreate('</(' + arrayJoin(objectKeys(FORBID_CONTENTS), '|') + ')', 'i'), value)) {
|
|
825
|
+
if (regExpTest(/\/>/i, value)) {
|
|
893
826
|
_removeAttribute(name, currentNode);
|
|
894
827
|
continue;
|
|
895
828
|
}
|
|
@@ -1022,7 +955,7 @@
|
|
|
1022
955
|
if (IN_PLACE) ; else if (dirty instanceof Node) {
|
|
1023
956
|
/* If dirty is a DOM element, append to an empty document to avoid
|
|
1024
957
|
elements being stripped by the parser */
|
|
1025
|
-
body = _initDocument('
|
|
958
|
+
body = _initDocument('<!---->');
|
|
1026
959
|
importedNode = body.ownerDocument.importNode(dirty, true);
|
|
1027
960
|
if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {
|
|
1028
961
|
/* Node is already a body, use as is */
|