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.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.
|
|
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 =
|
|
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></title><img>');
|
|
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(/<\/
|
|
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, '<');
|
|
735
|
-
} else {
|
|
736
|
-
currentNode.innerHTML = stringReplace(currentNode.textContent, /</g, '<');
|
|
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
|
-
|
|
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 (
|
|
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 */
|