dompurify 3.1.0 → 3.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/dist/purify.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! @license DOMPurify 3.1.0 | (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.0/LICENSE */
1
+ /*! @license DOMPurify 3.1.1 | (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.1/LICENSE */
2
2
 
3
3
  (function (global, factory) {
4
4
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
@@ -288,7 +288,7 @@
288
288
  * Version label, exposed for easier checks
289
289
  * if DOMPurify is up to date or not
290
290
  */
291
- DOMPurify.version = '3.1.0';
291
+ DOMPurify.version = '3.1.1';
292
292
 
293
293
  /**
294
294
  * Array of elements that DOMPurify removed during sanitation.
@@ -521,6 +521,9 @@
521
521
  /* Keep a reference to config to pass to hooks */
522
522
  let CONFIG = null;
523
523
 
524
+ /* Specify the maximum element nesting depth to prevent mXSS */
525
+ const MAX_NESTING_DEPTH = 255;
526
+
524
527
  /* Ideally, do not touch anything below this line */
525
528
  /* ______________________________________________ */
526
529
 
@@ -931,7 +934,11 @@
931
934
  * @return {Boolean} true if clobbered, false if safe
932
935
  */
933
936
  const _isClobbered = function _isClobbered(elm) {
934
- return elm instanceof HTMLFormElement && (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string' || typeof elm.insertBefore !== 'function' || typeof elm.hasChildNodes !== 'function');
937
+ return elm instanceof HTMLFormElement && (
938
+ // eslint-disable-next-line unicorn/no-typeof-undefined
939
+ typeof elm.__depth !== 'undefined' && typeof elm.__depth !== 'number' ||
940
+ // eslint-disable-next-line unicorn/no-typeof-undefined
941
+ typeof elm.__removalCount !== 'undefined' && typeof elm.__removalCount !== 'number' || typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string' || typeof elm.insertBefore !== 'function' || typeof elm.hasChildNodes !== 'function');
935
942
  };
936
943
 
937
944
  /**
@@ -1029,7 +1036,9 @@
1029
1036
  if (childNodes && parentNode) {
1030
1037
  const childCount = childNodes.length;
1031
1038
  for (let i = childCount - 1; i >= 0; --i) {
1032
- parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));
1039
+ const childClone = cloneNode(childNodes[i], true);
1040
+ childClone.__removalCount = (currentNode.__removalCount || 0) + 1;
1041
+ parentNode.insertBefore(childClone, getNextSibling(currentNode));
1033
1042
  }
1034
1043
  }
1035
1044
  }
@@ -1262,8 +1271,27 @@
1262
1271
  continue;
1263
1272
  }
1264
1273
 
1274
+ /* Set the nesting depth of an element */
1275
+ if (shadowNode.nodeType === 1) {
1276
+ if (shadowNode.parentNode && shadowNode.parentNode.__depth) {
1277
+ /*
1278
+ We want the depth of the node in the original tree, which can
1279
+ change when it's removed from its parent.
1280
+ */
1281
+ shadowNode.__depth = (shadowNode.__removalCount || 0) + shadowNode.parentNode.__depth + 1;
1282
+ } else {
1283
+ shadowNode.__depth = 1;
1284
+ }
1285
+ }
1286
+
1287
+ /* Remove an element if nested too deeply to avoid mXSS */
1288
+ if (shadowNode.__depth >= MAX_NESTING_DEPTH) {
1289
+ _forceRemove(shadowNode);
1290
+ }
1291
+
1265
1292
  /* Deep shadow DOM detected */
1266
1293
  if (shadowNode.content instanceof DocumentFragment) {
1294
+ shadowNode.content.__depth = shadowNode.__depth;
1267
1295
  _sanitizeShadowDOM(shadowNode.content);
1268
1296
  }
1269
1297
 
@@ -1380,8 +1408,27 @@
1380
1408
  continue;
1381
1409
  }
1382
1410
 
1411
+ /* Set the nesting depth of an element */
1412
+ if (currentNode.nodeType === 1) {
1413
+ if (currentNode.parentNode && currentNode.parentNode.__depth) {
1414
+ /*
1415
+ We want the depth of the node in the original tree, which can
1416
+ change when it's removed from its parent.
1417
+ */
1418
+ currentNode.__depth = (currentNode.__removalCount || 0) + currentNode.parentNode.__depth + 1;
1419
+ } else {
1420
+ currentNode.__depth = 1;
1421
+ }
1422
+ }
1423
+
1424
+ /* Remove an element if nested too deeply to avoid mXSS */
1425
+ if (currentNode.__depth >= MAX_NESTING_DEPTH) {
1426
+ _forceRemove(currentNode);
1427
+ }
1428
+
1383
1429
  /* Shadow DOM detected, sanitize it */
1384
1430
  if (currentNode.content instanceof DocumentFragment) {
1431
+ currentNode.content.__depth = currentNode.__depth;
1385
1432
  _sanitizeShadowDOM(currentNode.content);
1386
1433
  }
1387
1434