dompurify 3.1.4 → 3.1.6

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.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 */
1
+ /*! @license DOMPurify 3.1.6 | (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.6/LICENSE */
2
2
 
3
3
  (function (global, factory) {
4
4
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
@@ -54,10 +54,6 @@
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
- }
61
57
 
62
58
  /**
63
59
  * Creates a new function that calls the given function with a specified thisArg and arguments.
@@ -219,11 +215,9 @@
219
215
  const ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
220
216
  const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape
221
217
  );
222
-
223
218
  const IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
224
219
  const ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex
225
220
  );
226
-
227
221
  const DOCTYPE_NAME = seal(/^html$/i);
228
222
  const CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i);
229
223
 
@@ -258,7 +252,6 @@
258
252
  documentFragment: 11,
259
253
  notation: 12 // Deprecated
260
254
  };
261
-
262
255
  const getGlobal = function getGlobal() {
263
256
  return typeof window === 'undefined' ? null : window;
264
257
  };
@@ -310,7 +303,7 @@
310
303
  * Version label, exposed for easier checks
311
304
  * if DOMPurify is up to date or not
312
305
  */
313
- DOMPurify.version = '3.1.4';
306
+ DOMPurify.version = '3.1.6';
314
307
 
315
308
  /**
316
309
  * Array of elements that DOMPurify removed during sanitation.
@@ -341,6 +334,7 @@
341
334
  } = window;
342
335
  const ElementPrototype = Element.prototype;
343
336
  const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
337
+ const remove = lookupGetter(ElementPrototype, 'remove');
344
338
  const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
345
339
  const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
346
340
  const getParentNode = lookupGetter(ElementPrototype, 'parentNode');
@@ -543,9 +537,6 @@
543
537
  /* Keep a reference to config to pass to hooks */
544
538
  let CONFIG = null;
545
539
 
546
- /* Specify the maximum element nesting depth to prevent mXSS */
547
- const MAX_NESTING_DEPTH = 255;
548
-
549
540
  /* Ideally, do not touch anything below this line */
550
541
  /* ______________________________________________ */
551
542
 
@@ -844,9 +835,9 @@
844
835
  });
845
836
  try {
846
837
  // eslint-disable-next-line unicorn/prefer-dom-node-remove
847
- node.parentNode.removeChild(node);
838
+ getParentNode(node).removeChild(node);
848
839
  } catch (_) {
849
- node.remove();
840
+ remove(node);
850
841
  }
851
842
  };
852
843
 
@@ -956,11 +947,7 @@
956
947
  * @return {Boolean} true if clobbered, false if safe
957
948
  */
958
949
  const _isClobbered = function _isClobbered(elm) {
959
- return elm instanceof HTMLFormElement && (
960
- // eslint-disable-next-line unicorn/no-typeof-undefined
961
- typeof elm.__depth !== 'undefined' && typeof elm.__depth !== 'number' ||
962
- // eslint-disable-next-line unicorn/no-typeof-undefined
963
- 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');
950
+ 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');
964
951
  };
965
952
 
966
953
  /**
@@ -1027,7 +1014,7 @@
1027
1014
  return true;
1028
1015
  }
1029
1016
 
1030
- /* Remove any ocurrence of processing instructions */
1017
+ /* Remove any occurrence of processing instructions */
1031
1018
  if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {
1032
1019
  _forceRemove(currentNode);
1033
1020
  return true;
@@ -1111,7 +1098,7 @@
1111
1098
  // eslint-disable-next-line complexity
1112
1099
  const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
1113
1100
  /* Make sure attribute cannot clobber */
1114
- if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement || value === '__depth' || value === '__removalCount')) {
1101
+ if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
1115
1102
  return false;
1116
1103
  }
1117
1104
 
@@ -1196,6 +1183,13 @@
1196
1183
  hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
1197
1184
  _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
1198
1185
  value = hookEvent.attrValue;
1186
+
1187
+ /* Work around a security issue with comments inside attributes */
1188
+ if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|title)/i, value)) {
1189
+ _removeAttribute(name, currentNode);
1190
+ continue;
1191
+ }
1192
+
1199
1193
  /* Did the hooks approve of the attribute? */
1200
1194
  if (hookEvent.forceKeepAttr) {
1201
1195
  continue;
@@ -1215,12 +1209,6 @@
1215
1209
  continue;
1216
1210
  }
1217
1211
 
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
-
1224
1212
  /* Sanitize attribute content to be template-safe */
1225
1213
  if (SAFE_FOR_TEMPLATES) {
1226
1214
  arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
@@ -1302,32 +1290,9 @@
1302
1290
  if (_sanitizeElements(shadowNode)) {
1303
1291
  continue;
1304
1292
  }
1305
- const parentNode = getParentNode(shadowNode);
1306
-
1307
- /* Set the nesting depth of an element */
1308
- if (shadowNode.nodeType === NODE_TYPE.element) {
1309
- if (parentNode && parentNode.__depth) {
1310
- /*
1311
- We want the depth of the node in the original tree, which can
1312
- change when it's removed from its parent.
1313
- */
1314
- shadowNode.__depth = (shadowNode.__removalCount || 0) + parentNode.__depth + 1;
1315
- } else {
1316
- shadowNode.__depth = 1;
1317
- }
1318
- }
1319
-
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)) {
1325
- _forceRemove(shadowNode);
1326
- }
1327
1293
 
1328
1294
  /* Deep shadow DOM detected */
1329
1295
  if (shadowNode.content instanceof DocumentFragment) {
1330
- shadowNode.content.__depth = shadowNode.__depth;
1331
1296
  _sanitizeShadowDOM(shadowNode.content);
1332
1297
  }
1333
1298
 
@@ -1443,32 +1408,9 @@
1443
1408
  if (_sanitizeElements(currentNode)) {
1444
1409
  continue;
1445
1410
  }
1446
- const parentNode = getParentNode(currentNode);
1447
-
1448
- /* Set the nesting depth of an element */
1449
- if (currentNode.nodeType === NODE_TYPE.element) {
1450
- if (parentNode && parentNode.__depth) {
1451
- /*
1452
- We want the depth of the node in the original tree, which can
1453
- change when it's removed from its parent.
1454
- */
1455
- currentNode.__depth = (currentNode.__removalCount || 0) + parentNode.__depth + 1;
1456
- } else {
1457
- currentNode.__depth = 1;
1458
- }
1459
- }
1460
-
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)) {
1466
- _forceRemove(currentNode);
1467
- }
1468
1411
 
1469
1412
  /* Shadow DOM detected, sanitize it */
1470
1413
  if (currentNode.content instanceof DocumentFragment) {
1471
- currentNode.content.__depth = currentNode.__depth;
1472
1414
  _sanitizeShadowDOM(currentNode.content);
1473
1415
  }
1474
1416