dompurify 2.0.8 → 2.0.12
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 +34 -21
- package/dist/purify.cjs.js +56 -94
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.js +56 -94
- package/dist/purify.es.js.map +1 -1
- package/dist/purify.js +1002 -1040
- package/dist/purify.js.map +1 -1
- package/dist/purify.min.js +2 -1
- package/dist/purify.min.js.map +1 -1
- package/package.json +20 -17
package/dist/purify.es.js
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
|
|
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.0.8/LICENSE */
|
|
2
|
+
|
|
3
|
+
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); } }
|
|
2
4
|
|
|
3
|
-
var hasOwnProperty = Object.hasOwnProperty
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
var freeze = Object.freeze
|
|
8
|
-
|
|
5
|
+
var hasOwnProperty = Object.hasOwnProperty,
|
|
6
|
+
setPrototypeOf = Object.setPrototypeOf,
|
|
7
|
+
isFrozen = Object.isFrozen,
|
|
8
|
+
objectKeys = Object.keys;
|
|
9
|
+
var freeze = Object.freeze,
|
|
10
|
+
seal = Object.seal; // eslint-disable-line import/no-mutable-exports
|
|
9
11
|
|
|
10
|
-
var _ref = typeof Reflect !== 'undefined' && Reflect
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
var _ref = typeof Reflect !== 'undefined' && Reflect,
|
|
13
|
+
apply = _ref.apply,
|
|
14
|
+
construct = _ref.construct;
|
|
13
15
|
|
|
14
16
|
if (!apply) {
|
|
15
17
|
apply = function apply(fun, thisValue, args) {
|
|
@@ -31,7 +33,7 @@ if (!seal) {
|
|
|
31
33
|
|
|
32
34
|
if (!construct) {
|
|
33
35
|
construct = function construct(Func, args) {
|
|
34
|
-
return new (Function.prototype.bind.apply(Func, [null].concat(_toConsumableArray
|
|
36
|
+
return new (Function.prototype.bind.apply(Func, [null].concat(_toConsumableArray(args))))();
|
|
35
37
|
};
|
|
36
38
|
}
|
|
37
39
|
|
|
@@ -128,14 +130,15 @@ var mathMl = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph',
|
|
|
128
130
|
|
|
129
131
|
var text = freeze(['#text']);
|
|
130
132
|
|
|
131
|
-
var html$1 = freeze(['accept', 'action', 'align', 'alt', 'autocomplete', 'background', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', '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', 'minlength', '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']);
|
|
133
|
+
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']);
|
|
132
134
|
|
|
133
|
-
var svg$1 = freeze(['accent-height', 'accumulate', 'additive', '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', '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', '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', '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']);
|
|
135
|
+
var svg$1 = freeze(['accent-height', 'accumulate', 'additive', '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', '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', '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']);
|
|
134
136
|
|
|
135
137
|
var mathMl$1 = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);
|
|
136
138
|
|
|
137
139
|
var xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
|
|
138
140
|
|
|
141
|
+
// eslint-disable-next-line unicorn/better-regex
|
|
139
142
|
var MUSTACHE_EXPR = seal(/\{\{[\s\S]*|[\s\S]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
|
|
140
143
|
var ERB_EXPR = seal(/<%[\s\S]*|[\s\S]*%>/gm);
|
|
141
144
|
var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/); // eslint-disable-line no-useless-escape
|
|
@@ -148,7 +151,7 @@ var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\
|
|
|
148
151
|
|
|
149
152
|
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; };
|
|
150
153
|
|
|
151
|
-
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); } }
|
|
154
|
+
function _toConsumableArray$1(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); } }
|
|
152
155
|
|
|
153
156
|
var getGlobal = function getGlobal() {
|
|
154
157
|
return typeof window === 'undefined' ? null : window;
|
|
@@ -184,7 +187,7 @@ var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes,
|
|
|
184
187
|
return html$$1;
|
|
185
188
|
}
|
|
186
189
|
});
|
|
187
|
-
} catch (
|
|
190
|
+
} catch (_) {
|
|
188
191
|
// Policy creation failed (most likely another DOMPurify script has
|
|
189
192
|
// already run). Skip creating the policy, as this will only cause errors
|
|
190
193
|
// if TT are enforced.
|
|
@@ -204,7 +207,7 @@ function createDOMPurify() {
|
|
|
204
207
|
* Version label, exposed for easier checks
|
|
205
208
|
* if DOMPurify is up to date or not
|
|
206
209
|
*/
|
|
207
|
-
DOMPurify.version = '2.0.
|
|
210
|
+
DOMPurify.version = '2.0.12';
|
|
208
211
|
|
|
209
212
|
/**
|
|
210
213
|
* Array of elements that DOMPurify removed during sanitation.
|
|
@@ -221,7 +224,6 @@ function createDOMPurify() {
|
|
|
221
224
|
}
|
|
222
225
|
|
|
223
226
|
var originalDocument = window.document;
|
|
224
|
-
var useDOMParser = false;
|
|
225
227
|
var removeTitle = false;
|
|
226
228
|
|
|
227
229
|
var document = window.document;
|
|
@@ -251,7 +253,7 @@ function createDOMPurify() {
|
|
|
251
253
|
}
|
|
252
254
|
|
|
253
255
|
var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
|
|
254
|
-
var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
|
|
256
|
+
var emptyHTML = trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML('') : '';
|
|
255
257
|
|
|
256
258
|
var _document = document,
|
|
257
259
|
implementation = _document.implementation,
|
|
@@ -284,11 +286,11 @@ function createDOMPurify() {
|
|
|
284
286
|
/* allowed element names */
|
|
285
287
|
|
|
286
288
|
var ALLOWED_TAGS = null;
|
|
287
|
-
var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(html), _toConsumableArray(svg), _toConsumableArray(svgFilters), _toConsumableArray(mathMl), _toConsumableArray(text)));
|
|
289
|
+
var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray$1(html), _toConsumableArray$1(svg), _toConsumableArray$1(svgFilters), _toConsumableArray$1(mathMl), _toConsumableArray$1(text)));
|
|
288
290
|
|
|
289
291
|
/* Allowed attribute names */
|
|
290
292
|
var ALLOWED_ATTR = null;
|
|
291
|
-
var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray(html$1), _toConsumableArray(svg$1), _toConsumableArray(mathMl$1), _toConsumableArray(xml)));
|
|
293
|
+
var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray$1(html$1), _toConsumableArray$1(svg$1), _toConsumableArray$1(mathMl$1), _toConsumableArray$1(xml)));
|
|
292
294
|
|
|
293
295
|
/* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
|
|
294
296
|
var FORBID_TAGS = null;
|
|
@@ -360,7 +362,8 @@ function createDOMPurify() {
|
|
|
360
362
|
var FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);
|
|
361
363
|
|
|
362
364
|
/* Tags that are safe for data: URIs */
|
|
363
|
-
var DATA_URI_TAGS =
|
|
365
|
+
var DATA_URI_TAGS = null;
|
|
366
|
+
var DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);
|
|
364
367
|
|
|
365
368
|
/* Attributes safe for values like "javascript:" */
|
|
366
369
|
var URI_SAFE_ATTRIBUTES = null;
|
|
@@ -394,6 +397,7 @@ function createDOMPurify() {
|
|
|
394
397
|
ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;
|
|
395
398
|
ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
|
|
396
399
|
URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR) : DEFAULT_URI_SAFE_ATTRIBUTES;
|
|
400
|
+
DATA_URI_TAGS = 'ADD_DATA_URI_TAGS' in cfg ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS) : DEFAULT_DATA_URI_TAGS;
|
|
397
401
|
FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};
|
|
398
402
|
FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};
|
|
399
403
|
USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
|
|
@@ -422,7 +426,7 @@ function createDOMPurify() {
|
|
|
422
426
|
|
|
423
427
|
/* Parse profile info */
|
|
424
428
|
if (USE_PROFILES) {
|
|
425
|
-
ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(text)));
|
|
429
|
+
ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray$1(text)));
|
|
426
430
|
ALLOWED_ATTR = [];
|
|
427
431
|
if (USE_PROFILES.html === true) {
|
|
428
432
|
addToSet(ALLOWED_TAGS, html);
|
|
@@ -502,8 +506,9 @@ function createDOMPurify() {
|
|
|
502
506
|
var _forceRemove = function _forceRemove(node) {
|
|
503
507
|
arrayPush(DOMPurify.removed, { element: node });
|
|
504
508
|
try {
|
|
509
|
+
// eslint-disable-next-line unicorn/prefer-node-remove
|
|
505
510
|
node.parentNode.removeChild(node);
|
|
506
|
-
} catch (
|
|
511
|
+
} catch (_) {
|
|
507
512
|
node.outerHTML = emptyHTML;
|
|
508
513
|
}
|
|
509
514
|
};
|
|
@@ -520,7 +525,7 @@ function createDOMPurify() {
|
|
|
520
525
|
attribute: node.getAttributeNode(name),
|
|
521
526
|
from: node
|
|
522
527
|
});
|
|
523
|
-
} catch (
|
|
528
|
+
} catch (_) {
|
|
524
529
|
arrayPush(DOMPurify.removed, {
|
|
525
530
|
attribute: null,
|
|
526
531
|
from: node
|
|
@@ -545,25 +550,22 @@ function createDOMPurify() {
|
|
|
545
550
|
dirty = '<remove></remove>' + dirty;
|
|
546
551
|
} else {
|
|
547
552
|
/* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
|
|
548
|
-
var matches = stringMatch(dirty, /^[\
|
|
553
|
+
var matches = stringMatch(dirty, /^[\r\n\t ]+/);
|
|
549
554
|
leadingWhitespace = matches && matches[0];
|
|
550
555
|
}
|
|
551
556
|
|
|
552
557
|
var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
|
|
553
|
-
/* Use DOMParser
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
} catch (error) {}
|
|
558
|
-
}
|
|
558
|
+
/* Use the DOMParser API by default, fallback later if needs be */
|
|
559
|
+
try {
|
|
560
|
+
doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
|
|
561
|
+
} catch (_) {}
|
|
559
562
|
|
|
560
563
|
/* Remove title to fix a mXSS bug in older MS Edge */
|
|
561
564
|
if (removeTitle) {
|
|
562
565
|
addToSet(FORBID_TAGS, ['title']);
|
|
563
566
|
}
|
|
564
567
|
|
|
565
|
-
/*
|
|
566
|
-
Safari (see comment below) */
|
|
568
|
+
/* Use createHTMLDocument in case DOMParser is not available */
|
|
567
569
|
if (!doc || !doc.documentElement) {
|
|
568
570
|
doc = implementation.createHTMLDocument('');
|
|
569
571
|
var _doc = doc,
|
|
@@ -581,32 +583,15 @@ function createDOMPurify() {
|
|
|
581
583
|
return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
|
|
582
584
|
};
|
|
583
585
|
|
|
584
|
-
|
|
585
|
-
// DOMParser (see https://bugzilla.mozilla.org/show_bug.cgi?id=1205631)
|
|
586
|
-
// which means that you *must* use DOMParser, otherwise the output may
|
|
587
|
-
// not be safe if used in a document.write context later.
|
|
588
|
-
//
|
|
589
|
-
// So we feature detect the Firefox bug and use the DOMParser if necessary.
|
|
590
|
-
//
|
|
591
|
-
// Chrome 77 and other versions ship an mXSS bug that caused a bypass to
|
|
592
|
-
// happen. We now check for the mXSS trigger and react accordingly.
|
|
586
|
+
/* Here we test for a broken feature in Edge that might cause mXSS */
|
|
593
587
|
if (DOMPurify.isSupported) {
|
|
594
|
-
(function () {
|
|
595
|
-
try {
|
|
596
|
-
var doc = _initDocument('<svg><p><textarea><img src="</textarea><img src=x abc=1//">');
|
|
597
|
-
if (doc.querySelector('svg img')) {
|
|
598
|
-
useDOMParser = true;
|
|
599
|
-
}
|
|
600
|
-
} catch (error) {}
|
|
601
|
-
})();
|
|
602
|
-
|
|
603
588
|
(function () {
|
|
604
589
|
try {
|
|
605
590
|
var doc = _initDocument('<x/><title></title><img>');
|
|
606
591
|
if (regExpTest(/<\/title/, doc.querySelector('title').innerHTML)) {
|
|
607
592
|
removeTitle = true;
|
|
608
593
|
}
|
|
609
|
-
} catch (
|
|
594
|
+
} catch (_) {}
|
|
610
595
|
})();
|
|
611
596
|
}
|
|
612
597
|
|
|
@@ -646,8 +631,8 @@ function createDOMPurify() {
|
|
|
646
631
|
* @param {Node} obj object to check whether it's a DOM node
|
|
647
632
|
* @return {Boolean} true is object is a DOM node
|
|
648
633
|
*/
|
|
649
|
-
var _isNode = function _isNode(
|
|
650
|
-
return (typeof Node === 'undefined' ? 'undefined' : _typeof(Node)) === 'object' ?
|
|
634
|
+
var _isNode = function _isNode(object) {
|
|
635
|
+
return (typeof Node === 'undefined' ? 'undefined' : _typeof(Node)) === 'object' ? object instanceof Node : object && (typeof object === 'undefined' ? 'undefined' : _typeof(object)) === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string';
|
|
651
636
|
};
|
|
652
637
|
|
|
653
638
|
/**
|
|
@@ -708,12 +693,12 @@ function createDOMPurify() {
|
|
|
708
693
|
|
|
709
694
|
/* Remove element if anything forbids its presence */
|
|
710
695
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
711
|
-
/* Keep content except for
|
|
696
|
+
/* Keep content except for bad-listed elements */
|
|
712
697
|
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName] && typeof currentNode.insertAdjacentHTML === 'function') {
|
|
713
698
|
try {
|
|
714
699
|
var htmlToInsert = currentNode.innerHTML;
|
|
715
700
|
currentNode.insertAdjacentHTML('AfterEnd', trustedTypesPolicy ? trustedTypesPolicy.createHTML(htmlToInsert) : htmlToInsert);
|
|
716
|
-
} catch (
|
|
701
|
+
} catch (_) {}
|
|
717
702
|
}
|
|
718
703
|
|
|
719
704
|
_forceRemove(currentNode);
|
|
@@ -778,36 +763,11 @@ function createDOMPurify() {
|
|
|
778
763
|
(https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
|
|
779
764
|
XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
|
|
780
765
|
We don't need to check the value; it's always URI safe. */
|
|
781
|
-
if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$$1, lcName)) {
|
|
782
|
-
// This attribute is safe
|
|
783
|
-
} else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$$1, lcName)) {
|
|
784
|
-
// This attribute is safe
|
|
785
|
-
/* Otherwise, check the name is permitted */
|
|
786
|
-
} else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
|
|
766
|
+
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]) {
|
|
787
767
|
return false;
|
|
788
768
|
|
|
789
769
|
/* Check value is safe. First, is attr inert? If so, is safe */
|
|
790
|
-
} else if (URI_SAFE_ATTRIBUTES[lcName]) {
|
|
791
|
-
// This attribute is safe
|
|
792
|
-
/* Check no script, data or unknown possibly unsafe URI
|
|
793
|
-
unless we know URI values are safe for that attribute */
|
|
794
|
-
} else if (regExpTest(IS_ALLOWED_URI$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) {
|
|
795
|
-
// This attribute is safe
|
|
796
|
-
/* Keep image data URIs alive if src/xlink:href is allowed */
|
|
797
|
-
/* Further prevent gadget XSS for dynamically built script tags */
|
|
798
|
-
} else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) {
|
|
799
|
-
// This attribute is safe
|
|
800
|
-
/* Allow unknown protocols: This provides support for links that
|
|
801
|
-
are handled by protocol handlers which may be unknown ahead of
|
|
802
|
-
time, e.g. fb:, spotify: */
|
|
803
|
-
} else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) {
|
|
804
|
-
// This attribute is safe
|
|
805
|
-
/* Check for binary attributes */
|
|
806
|
-
// eslint-disable-next-line no-negated-condition
|
|
807
|
-
} else if (!value) {
|
|
808
|
-
// Binary attributes are safe at this point
|
|
809
|
-
/* Anything else, presume unsafe, do not add it back */
|
|
810
|
-
} else {
|
|
770
|
+
} else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) ; else if (!value) ; else {
|
|
811
771
|
return false;
|
|
812
772
|
}
|
|
813
773
|
|
|
@@ -939,7 +899,7 @@ function createDOMPurify() {
|
|
|
939
899
|
}
|
|
940
900
|
|
|
941
901
|
arrayPop(DOMPurify.removed);
|
|
942
|
-
} catch (
|
|
902
|
+
} catch (_) {}
|
|
943
903
|
}
|
|
944
904
|
|
|
945
905
|
/* Execute a hook if present */
|
|
@@ -1042,9 +1002,7 @@ function createDOMPurify() {
|
|
|
1042
1002
|
IN_PLACE = false;
|
|
1043
1003
|
}
|
|
1044
1004
|
|
|
1045
|
-
if (IN_PLACE) {
|
|
1046
|
-
/* No special handling necessary for in-place sanitization */
|
|
1047
|
-
} else if (dirty instanceof Node) {
|
|
1005
|
+
if (IN_PLACE) ; else if (dirty instanceof Node) {
|
|
1048
1006
|
/* If dirty is a DOM element, append to an empty document to avoid
|
|
1049
1007
|
elements being stripped by the parser */
|
|
1050
1008
|
body = _initDocument('<!-->');
|
|
@@ -1060,8 +1018,10 @@ function createDOMPurify() {
|
|
|
1060
1018
|
}
|
|
1061
1019
|
} else {
|
|
1062
1020
|
/* Exit directly if we have nothing to do */
|
|
1063
|
-
if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&
|
|
1064
|
-
|
|
1021
|
+
if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&
|
|
1022
|
+
// eslint-disable-next-line unicorn/prefer-includes
|
|
1023
|
+
dirty.indexOf('<') === -1) {
|
|
1024
|
+
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
|
|
1065
1025
|
}
|
|
1066
1026
|
|
|
1067
1027
|
/* Initialize the document to work on */
|
|
@@ -1125,11 +1085,13 @@ function createDOMPurify() {
|
|
|
1125
1085
|
}
|
|
1126
1086
|
|
|
1127
1087
|
if (RETURN_DOM_IMPORT) {
|
|
1128
|
-
/*
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1088
|
+
/*
|
|
1089
|
+
AdoptNode() is not used because internal state is not reset
|
|
1090
|
+
(e.g. the past names map of a HTMLFormElement), this is safe
|
|
1091
|
+
in theory but we would rather not risk another attack vector.
|
|
1092
|
+
The state that is cloned by importNode() is explicitly defined
|
|
1093
|
+
by the specs.
|
|
1094
|
+
*/
|
|
1133
1095
|
returnNode = importNode.call(originalDocument, returnNode, true);
|
|
1134
1096
|
}
|
|
1135
1097
|
|