dompurify 3.1.1 → 3.1.3
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 +3 -3
- package/dist/purify.cjs.js +57 -20
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.mjs +57 -20
- package/dist/purify.es.mjs.map +1 -1
- package/dist/purify.js +57 -20
- 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.3 | (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.3/LICENSE */
|
|
2
2
|
|
|
3
3
|
(function (global, factory) {
|
|
4
4
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
|
|
55
55
|
const regExpTest = unapply(RegExp.prototype.test);
|
|
56
56
|
const typeErrorCreate = unconstruct(TypeError);
|
|
57
|
+
const numberIsNaN = unapply(Number.isNaN);
|
|
57
58
|
|
|
58
59
|
/**
|
|
59
60
|
* Creates a new function that calls the given function with a specified thisArg and arguments.
|
|
@@ -237,6 +238,24 @@
|
|
|
237
238
|
CUSTOM_ELEMENT: CUSTOM_ELEMENT
|
|
238
239
|
});
|
|
239
240
|
|
|
241
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
|
|
242
|
+
const NODE_TYPE = {
|
|
243
|
+
element: 1,
|
|
244
|
+
attribute: 2,
|
|
245
|
+
text: 3,
|
|
246
|
+
cdataSection: 4,
|
|
247
|
+
entityReference: 5,
|
|
248
|
+
// Deprecated
|
|
249
|
+
entityNode: 6,
|
|
250
|
+
// Deprecated
|
|
251
|
+
progressingInstruction: 7,
|
|
252
|
+
comment: 8,
|
|
253
|
+
document: 9,
|
|
254
|
+
documentType: 10,
|
|
255
|
+
documentFragment: 11,
|
|
256
|
+
notation: 12 // Deprecated
|
|
257
|
+
};
|
|
258
|
+
|
|
240
259
|
const getGlobal = function getGlobal() {
|
|
241
260
|
return typeof window === 'undefined' ? null : window;
|
|
242
261
|
};
|
|
@@ -288,14 +307,14 @@
|
|
|
288
307
|
* Version label, exposed for easier checks
|
|
289
308
|
* if DOMPurify is up to date or not
|
|
290
309
|
*/
|
|
291
|
-
DOMPurify.version = '3.1.
|
|
310
|
+
DOMPurify.version = '3.1.3';
|
|
292
311
|
|
|
293
312
|
/**
|
|
294
313
|
* Array of elements that DOMPurify removed during sanitation.
|
|
295
314
|
* Empty if nothing was removed.
|
|
296
315
|
*/
|
|
297
316
|
DOMPurify.removed = [];
|
|
298
|
-
if (!window || !window.document || window.document.nodeType !==
|
|
317
|
+
if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document) {
|
|
299
318
|
// Not running in a browser, provide a factory function
|
|
300
319
|
// so that you can pass your own Window
|
|
301
320
|
DOMPurify.isSupported = false;
|
|
@@ -710,7 +729,7 @@
|
|
|
710
729
|
CONFIG = cfg;
|
|
711
730
|
};
|
|
712
731
|
const MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);
|
|
713
|
-
const HTML_INTEGRATION_POINTS = addToSet({}, ['foreignobject', '
|
|
732
|
+
const HTML_INTEGRATION_POINTS = addToSet({}, ['foreignobject', 'annotation-xml']);
|
|
714
733
|
|
|
715
734
|
// Certain elements are allowed in both SVG and HTML
|
|
716
735
|
// namespace. We need to specify them explicitly
|
|
@@ -1006,13 +1025,13 @@
|
|
|
1006
1025
|
}
|
|
1007
1026
|
|
|
1008
1027
|
/* Remove any ocurrence of processing instructions */
|
|
1009
|
-
if (currentNode.nodeType ===
|
|
1028
|
+
if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {
|
|
1010
1029
|
_forceRemove(currentNode);
|
|
1011
1030
|
return true;
|
|
1012
1031
|
}
|
|
1013
1032
|
|
|
1014
1033
|
/* Remove any kind of possibly harmful comments */
|
|
1015
|
-
if (SAFE_FOR_XML && currentNode.nodeType ===
|
|
1034
|
+
if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(/<[/\w]/g, currentNode.data)) {
|
|
1016
1035
|
_forceRemove(currentNode);
|
|
1017
1036
|
return true;
|
|
1018
1037
|
}
|
|
@@ -1059,7 +1078,7 @@
|
|
|
1059
1078
|
}
|
|
1060
1079
|
|
|
1061
1080
|
/* Sanitize element content to be template-safe */
|
|
1062
|
-
if (SAFE_FOR_TEMPLATES && currentNode.nodeType ===
|
|
1081
|
+
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {
|
|
1063
1082
|
/* Get the element's text content */
|
|
1064
1083
|
content = currentNode.textContent;
|
|
1065
1084
|
arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
|
|
@@ -1089,7 +1108,7 @@
|
|
|
1089
1108
|
// eslint-disable-next-line complexity
|
|
1090
1109
|
const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
|
|
1091
1110
|
/* Make sure attribute cannot clobber */
|
|
1092
|
-
if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
|
|
1111
|
+
if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement || value === '__depth' || value === '__removalCount')) {
|
|
1093
1112
|
return false;
|
|
1094
1113
|
}
|
|
1095
1114
|
|
|
@@ -1193,6 +1212,12 @@
|
|
|
1193
1212
|
continue;
|
|
1194
1213
|
}
|
|
1195
1214
|
|
|
1215
|
+
/* Work around a security issue with comments inside attributes */
|
|
1216
|
+
if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|title)/i, value)) {
|
|
1217
|
+
_removeAttribute(name, currentNode);
|
|
1218
|
+
continue;
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1196
1221
|
/* Sanitize attribute content to be template-safe */
|
|
1197
1222
|
if (SAFE_FOR_TEMPLATES) {
|
|
1198
1223
|
arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
|
|
@@ -1243,7 +1268,11 @@
|
|
|
1243
1268
|
/* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
|
|
1244
1269
|
currentNode.setAttribute(name, value);
|
|
1245
1270
|
}
|
|
1246
|
-
|
|
1271
|
+
if (_isClobbered(currentNode)) {
|
|
1272
|
+
_forceRemove(currentNode);
|
|
1273
|
+
} else {
|
|
1274
|
+
arrayPop(DOMPurify.removed);
|
|
1275
|
+
}
|
|
1247
1276
|
} catch (_) {}
|
|
1248
1277
|
}
|
|
1249
1278
|
|
|
@@ -1270,22 +1299,26 @@
|
|
|
1270
1299
|
if (_sanitizeElements(shadowNode)) {
|
|
1271
1300
|
continue;
|
|
1272
1301
|
}
|
|
1302
|
+
const parentNode = getParentNode(shadowNode);
|
|
1273
1303
|
|
|
1274
1304
|
/* Set the nesting depth of an element */
|
|
1275
|
-
if (shadowNode.nodeType ===
|
|
1276
|
-
if (
|
|
1305
|
+
if (shadowNode.nodeType === NODE_TYPE.element) {
|
|
1306
|
+
if (parentNode && parentNode.__depth) {
|
|
1277
1307
|
/*
|
|
1278
1308
|
We want the depth of the node in the original tree, which can
|
|
1279
1309
|
change when it's removed from its parent.
|
|
1280
1310
|
*/
|
|
1281
|
-
shadowNode.__depth = (shadowNode.__removalCount || 0) +
|
|
1311
|
+
shadowNode.__depth = (shadowNode.__removalCount || 0) + parentNode.__depth + 1;
|
|
1282
1312
|
} else {
|
|
1283
1313
|
shadowNode.__depth = 1;
|
|
1284
1314
|
}
|
|
1285
1315
|
}
|
|
1286
1316
|
|
|
1287
|
-
/*
|
|
1288
|
-
|
|
1317
|
+
/*
|
|
1318
|
+
* Remove an element if nested too deeply to avoid mXSS
|
|
1319
|
+
* or if the __depth might have been tampered with
|
|
1320
|
+
*/
|
|
1321
|
+
if (shadowNode.__depth >= MAX_NESTING_DEPTH || shadowNode.__depth < 0 || numberIsNaN(shadowNode.__depth)) {
|
|
1289
1322
|
_forceRemove(shadowNode);
|
|
1290
1323
|
}
|
|
1291
1324
|
|
|
@@ -1367,7 +1400,7 @@
|
|
|
1367
1400
|
elements being stripped by the parser */
|
|
1368
1401
|
body = _initDocument('<!---->');
|
|
1369
1402
|
importedNode = body.ownerDocument.importNode(dirty, true);
|
|
1370
|
-
if (importedNode.nodeType ===
|
|
1403
|
+
if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === 'BODY') {
|
|
1371
1404
|
/* Node is already a body, use as is */
|
|
1372
1405
|
body = importedNode;
|
|
1373
1406
|
} else if (importedNode.nodeName === 'HTML') {
|
|
@@ -1407,22 +1440,26 @@
|
|
|
1407
1440
|
if (_sanitizeElements(currentNode)) {
|
|
1408
1441
|
continue;
|
|
1409
1442
|
}
|
|
1443
|
+
const parentNode = getParentNode(currentNode);
|
|
1410
1444
|
|
|
1411
1445
|
/* Set the nesting depth of an element */
|
|
1412
|
-
if (currentNode.nodeType ===
|
|
1413
|
-
if (
|
|
1446
|
+
if (currentNode.nodeType === NODE_TYPE.element) {
|
|
1447
|
+
if (parentNode && parentNode.__depth) {
|
|
1414
1448
|
/*
|
|
1415
1449
|
We want the depth of the node in the original tree, which can
|
|
1416
1450
|
change when it's removed from its parent.
|
|
1417
1451
|
*/
|
|
1418
|
-
currentNode.__depth = (currentNode.__removalCount || 0) +
|
|
1452
|
+
currentNode.__depth = (currentNode.__removalCount || 0) + parentNode.__depth + 1;
|
|
1419
1453
|
} else {
|
|
1420
1454
|
currentNode.__depth = 1;
|
|
1421
1455
|
}
|
|
1422
1456
|
}
|
|
1423
1457
|
|
|
1424
|
-
/*
|
|
1425
|
-
|
|
1458
|
+
/*
|
|
1459
|
+
* Remove an element if nested too deeply to avoid mXSS
|
|
1460
|
+
* or if the __depth might have been tampered with
|
|
1461
|
+
*/
|
|
1462
|
+
if (currentNode.__depth >= MAX_NESTING_DEPTH || currentNode.__depth < 0 || numberIsNaN(currentNode.__depth)) {
|
|
1426
1463
|
_forceRemove(currentNode);
|
|
1427
1464
|
}
|
|
1428
1465
|
|