dompurify 3.1.2 → 3.1.4
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 +4 -4
- package/dist/purify.cjs.js +54 -16
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.mjs +54 -16
- package/dist/purify.es.mjs.map +1 -1
- package/dist/purify.js +54 -16
- package/dist/purify.js.map +1 -1
- package/dist/purify.min.js +2 -2
- package/dist/purify.min.js.map +1 -1
- package/package.json +1 -1
package/dist/purify.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @license DOMPurify 3.1.
|
|
1
|
+
/*! @license DOMPurify 3.1.4 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.1.4/LICENSE */
|
|
2
2
|
|
|
3
3
|
(function (global, factory) {
|
|
4
4
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
|
@@ -54,6 +54,10 @@
|
|
|
54
54
|
const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
|
|
55
55
|
const regExpTest = unapply(RegExp.prototype.test);
|
|
56
56
|
const typeErrorCreate = unconstruct(TypeError);
|
|
57
|
+
function numberIsNaN(x) {
|
|
58
|
+
// eslint-disable-next-line unicorn/prefer-number-properties
|
|
59
|
+
return typeof x === 'number' && isNaN(x);
|
|
60
|
+
}
|
|
57
61
|
|
|
58
62
|
/**
|
|
59
63
|
* Creates a new function that calls the given function with a specified thisArg and arguments.
|
|
@@ -202,7 +206,7 @@
|
|
|
202
206
|
const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
|
|
203
207
|
const text = freeze(['#text']);
|
|
204
208
|
|
|
205
|
-
const html = 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', 'nonce', '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', 'wrap', 'xmlns', 'slot']);
|
|
209
|
+
const html = 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', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', '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', 'wrap', 'xmlns', 'slot']);
|
|
206
210
|
const svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', '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', 'systemlanguage', 'tabindex', 'targetx', 'targety', 'transform', 'transform-origin', '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']);
|
|
207
211
|
const mathMl = 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']);
|
|
208
212
|
const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
|
|
@@ -237,6 +241,24 @@
|
|
|
237
241
|
CUSTOM_ELEMENT: CUSTOM_ELEMENT
|
|
238
242
|
});
|
|
239
243
|
|
|
244
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
|
|
245
|
+
const NODE_TYPE = {
|
|
246
|
+
element: 1,
|
|
247
|
+
attribute: 2,
|
|
248
|
+
text: 3,
|
|
249
|
+
cdataSection: 4,
|
|
250
|
+
entityReference: 5,
|
|
251
|
+
// Deprecated
|
|
252
|
+
entityNode: 6,
|
|
253
|
+
// Deprecated
|
|
254
|
+
progressingInstruction: 7,
|
|
255
|
+
comment: 8,
|
|
256
|
+
document: 9,
|
|
257
|
+
documentType: 10,
|
|
258
|
+
documentFragment: 11,
|
|
259
|
+
notation: 12 // Deprecated
|
|
260
|
+
};
|
|
261
|
+
|
|
240
262
|
const getGlobal = function getGlobal() {
|
|
241
263
|
return typeof window === 'undefined' ? null : window;
|
|
242
264
|
};
|
|
@@ -288,14 +310,14 @@
|
|
|
288
310
|
* Version label, exposed for easier checks
|
|
289
311
|
* if DOMPurify is up to date or not
|
|
290
312
|
*/
|
|
291
|
-
DOMPurify.version = '3.1.
|
|
313
|
+
DOMPurify.version = '3.1.4';
|
|
292
314
|
|
|
293
315
|
/**
|
|
294
316
|
* Array of elements that DOMPurify removed during sanitation.
|
|
295
317
|
* Empty if nothing was removed.
|
|
296
318
|
*/
|
|
297
319
|
DOMPurify.removed = [];
|
|
298
|
-
if (!window || !window.document || window.document.nodeType !==
|
|
320
|
+
if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document) {
|
|
299
321
|
// Not running in a browser, provide a factory function
|
|
300
322
|
// so that you can pass your own Window
|
|
301
323
|
DOMPurify.isSupported = false;
|
|
@@ -1006,13 +1028,13 @@
|
|
|
1006
1028
|
}
|
|
1007
1029
|
|
|
1008
1030
|
/* Remove any ocurrence of processing instructions */
|
|
1009
|
-
if (currentNode.nodeType ===
|
|
1031
|
+
if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {
|
|
1010
1032
|
_forceRemove(currentNode);
|
|
1011
1033
|
return true;
|
|
1012
1034
|
}
|
|
1013
1035
|
|
|
1014
1036
|
/* Remove any kind of possibly harmful comments */
|
|
1015
|
-
if (SAFE_FOR_XML && currentNode.nodeType ===
|
|
1037
|
+
if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(/<[/\w]/g, currentNode.data)) {
|
|
1016
1038
|
_forceRemove(currentNode);
|
|
1017
1039
|
return true;
|
|
1018
1040
|
}
|
|
@@ -1059,7 +1081,7 @@
|
|
|
1059
1081
|
}
|
|
1060
1082
|
|
|
1061
1083
|
/* Sanitize element content to be template-safe */
|
|
1062
|
-
if (SAFE_FOR_TEMPLATES && currentNode.nodeType ===
|
|
1084
|
+
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {
|
|
1063
1085
|
/* Get the element's text content */
|
|
1064
1086
|
content = currentNode.textContent;
|
|
1065
1087
|
arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
|
|
@@ -1089,7 +1111,7 @@
|
|
|
1089
1111
|
// eslint-disable-next-line complexity
|
|
1090
1112
|
const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
|
|
1091
1113
|
/* Make sure attribute cannot clobber */
|
|
1092
|
-
if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
|
|
1114
|
+
if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement || value === '__depth' || value === '__removalCount')) {
|
|
1093
1115
|
return false;
|
|
1094
1116
|
}
|
|
1095
1117
|
|
|
@@ -1193,6 +1215,12 @@
|
|
|
1193
1215
|
continue;
|
|
1194
1216
|
}
|
|
1195
1217
|
|
|
1218
|
+
/* Work around a security issue with comments inside attributes */
|
|
1219
|
+
if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|title)/i, value)) {
|
|
1220
|
+
_removeAttribute(name, currentNode);
|
|
1221
|
+
continue;
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1196
1224
|
/* Sanitize attribute content to be template-safe */
|
|
1197
1225
|
if (SAFE_FOR_TEMPLATES) {
|
|
1198
1226
|
arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
|
|
@@ -1243,7 +1271,11 @@
|
|
|
1243
1271
|
/* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
|
|
1244
1272
|
currentNode.setAttribute(name, value);
|
|
1245
1273
|
}
|
|
1246
|
-
|
|
1274
|
+
if (_isClobbered(currentNode)) {
|
|
1275
|
+
_forceRemove(currentNode);
|
|
1276
|
+
} else {
|
|
1277
|
+
arrayPop(DOMPurify.removed);
|
|
1278
|
+
}
|
|
1247
1279
|
} catch (_) {}
|
|
1248
1280
|
}
|
|
1249
1281
|
|
|
@@ -1273,7 +1305,7 @@
|
|
|
1273
1305
|
const parentNode = getParentNode(shadowNode);
|
|
1274
1306
|
|
|
1275
1307
|
/* Set the nesting depth of an element */
|
|
1276
|
-
if (shadowNode.nodeType ===
|
|
1308
|
+
if (shadowNode.nodeType === NODE_TYPE.element) {
|
|
1277
1309
|
if (parentNode && parentNode.__depth) {
|
|
1278
1310
|
/*
|
|
1279
1311
|
We want the depth of the node in the original tree, which can
|
|
@@ -1285,8 +1317,11 @@
|
|
|
1285
1317
|
}
|
|
1286
1318
|
}
|
|
1287
1319
|
|
|
1288
|
-
/*
|
|
1289
|
-
|
|
1320
|
+
/*
|
|
1321
|
+
* Remove an element if nested too deeply to avoid mXSS
|
|
1322
|
+
* or if the __depth might have been tampered with
|
|
1323
|
+
*/
|
|
1324
|
+
if (shadowNode.__depth >= MAX_NESTING_DEPTH || shadowNode.__depth < 0 || numberIsNaN(shadowNode.__depth)) {
|
|
1290
1325
|
_forceRemove(shadowNode);
|
|
1291
1326
|
}
|
|
1292
1327
|
|
|
@@ -1368,7 +1403,7 @@
|
|
|
1368
1403
|
elements being stripped by the parser */
|
|
1369
1404
|
body = _initDocument('<!---->');
|
|
1370
1405
|
importedNode = body.ownerDocument.importNode(dirty, true);
|
|
1371
|
-
if (importedNode.nodeType ===
|
|
1406
|
+
if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === 'BODY') {
|
|
1372
1407
|
/* Node is already a body, use as is */
|
|
1373
1408
|
body = importedNode;
|
|
1374
1409
|
} else if (importedNode.nodeName === 'HTML') {
|
|
@@ -1411,7 +1446,7 @@
|
|
|
1411
1446
|
const parentNode = getParentNode(currentNode);
|
|
1412
1447
|
|
|
1413
1448
|
/* Set the nesting depth of an element */
|
|
1414
|
-
if (currentNode.nodeType ===
|
|
1449
|
+
if (currentNode.nodeType === NODE_TYPE.element) {
|
|
1415
1450
|
if (parentNode && parentNode.__depth) {
|
|
1416
1451
|
/*
|
|
1417
1452
|
We want the depth of the node in the original tree, which can
|
|
@@ -1423,8 +1458,11 @@
|
|
|
1423
1458
|
}
|
|
1424
1459
|
}
|
|
1425
1460
|
|
|
1426
|
-
/*
|
|
1427
|
-
|
|
1461
|
+
/*
|
|
1462
|
+
* Remove an element if nested too deeply to avoid mXSS
|
|
1463
|
+
* or if the __depth might have been tampered with
|
|
1464
|
+
*/
|
|
1465
|
+
if (currentNode.__depth >= MAX_NESTING_DEPTH || currentNode.__depth < 0 || numberIsNaN(currentNode.__depth)) {
|
|
1428
1466
|
_forceRemove(currentNode);
|
|
1429
1467
|
}
|
|
1430
1468
|
|