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.
@@ -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
  const {
4
4
  entries,
@@ -48,10 +48,6 @@ const stringTrim = unapply(String.prototype.trim);
48
48
  const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
49
49
  const regExpTest = unapply(RegExp.prototype.test);
50
50
  const typeErrorCreate = unconstruct(TypeError);
51
- function numberIsNaN(x) {
52
- // eslint-disable-next-line unicorn/prefer-number-properties
53
- return typeof x === 'number' && isNaN(x);
54
- }
55
51
 
56
52
  /**
57
53
  * Creates a new function that calls the given function with a specified thisArg and arguments.
@@ -213,11 +209,9 @@ const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/); // eslint-disable-line no-
213
209
  const ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
214
210
  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
215
211
  );
216
-
217
212
  const IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
218
213
  const ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex
219
214
  );
220
-
221
215
  const DOCTYPE_NAME = seal(/^html$/i);
222
216
  const CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i);
223
217
 
@@ -252,7 +246,6 @@ const NODE_TYPE = {
252
246
  documentFragment: 11,
253
247
  notation: 12 // Deprecated
254
248
  };
255
-
256
249
  const getGlobal = function getGlobal() {
257
250
  return typeof window === 'undefined' ? null : window;
258
251
  };
@@ -304,7 +297,7 @@ function createDOMPurify() {
304
297
  * Version label, exposed for easier checks
305
298
  * if DOMPurify is up to date or not
306
299
  */
307
- DOMPurify.version = '3.1.4';
300
+ DOMPurify.version = '3.1.6';
308
301
 
309
302
  /**
310
303
  * Array of elements that DOMPurify removed during sanitation.
@@ -335,6 +328,7 @@ function createDOMPurify() {
335
328
  } = window;
336
329
  const ElementPrototype = Element.prototype;
337
330
  const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
331
+ const remove = lookupGetter(ElementPrototype, 'remove');
338
332
  const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
339
333
  const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
340
334
  const getParentNode = lookupGetter(ElementPrototype, 'parentNode');
@@ -537,9 +531,6 @@ function createDOMPurify() {
537
531
  /* Keep a reference to config to pass to hooks */
538
532
  let CONFIG = null;
539
533
 
540
- /* Specify the maximum element nesting depth to prevent mXSS */
541
- const MAX_NESTING_DEPTH = 255;
542
-
543
534
  /* Ideally, do not touch anything below this line */
544
535
  /* ______________________________________________ */
545
536
 
@@ -838,9 +829,9 @@ function createDOMPurify() {
838
829
  });
839
830
  try {
840
831
  // eslint-disable-next-line unicorn/prefer-dom-node-remove
841
- node.parentNode.removeChild(node);
832
+ getParentNode(node).removeChild(node);
842
833
  } catch (_) {
843
- node.remove();
834
+ remove(node);
844
835
  }
845
836
  };
846
837
 
@@ -950,11 +941,7 @@ function createDOMPurify() {
950
941
  * @return {Boolean} true if clobbered, false if safe
951
942
  */
952
943
  const _isClobbered = function _isClobbered(elm) {
953
- return elm instanceof HTMLFormElement && (
954
- // eslint-disable-next-line unicorn/no-typeof-undefined
955
- typeof elm.__depth !== 'undefined' && typeof elm.__depth !== 'number' ||
956
- // eslint-disable-next-line unicorn/no-typeof-undefined
957
- 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');
944
+ 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');
958
945
  };
959
946
 
960
947
  /**
@@ -1021,7 +1008,7 @@ function createDOMPurify() {
1021
1008
  return true;
1022
1009
  }
1023
1010
 
1024
- /* Remove any ocurrence of processing instructions */
1011
+ /* Remove any occurrence of processing instructions */
1025
1012
  if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {
1026
1013
  _forceRemove(currentNode);
1027
1014
  return true;
@@ -1105,7 +1092,7 @@ function createDOMPurify() {
1105
1092
  // eslint-disable-next-line complexity
1106
1093
  const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
1107
1094
  /* Make sure attribute cannot clobber */
1108
- if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement || value === '__depth' || value === '__removalCount')) {
1095
+ if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
1109
1096
  return false;
1110
1097
  }
1111
1098
 
@@ -1190,6 +1177,13 @@ function createDOMPurify() {
1190
1177
  hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
1191
1178
  _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
1192
1179
  value = hookEvent.attrValue;
1180
+
1181
+ /* Work around a security issue with comments inside attributes */
1182
+ if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|title)/i, value)) {
1183
+ _removeAttribute(name, currentNode);
1184
+ continue;
1185
+ }
1186
+
1193
1187
  /* Did the hooks approve of the attribute? */
1194
1188
  if (hookEvent.forceKeepAttr) {
1195
1189
  continue;
@@ -1209,12 +1203,6 @@ function createDOMPurify() {
1209
1203
  continue;
1210
1204
  }
1211
1205
 
1212
- /* Work around a security issue with comments inside attributes */
1213
- if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|title)/i, value)) {
1214
- _removeAttribute(name, currentNode);
1215
- continue;
1216
- }
1217
-
1218
1206
  /* Sanitize attribute content to be template-safe */
1219
1207
  if (SAFE_FOR_TEMPLATES) {
1220
1208
  arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
@@ -1296,32 +1284,9 @@ function createDOMPurify() {
1296
1284
  if (_sanitizeElements(shadowNode)) {
1297
1285
  continue;
1298
1286
  }
1299
- const parentNode = getParentNode(shadowNode);
1300
-
1301
- /* Set the nesting depth of an element */
1302
- if (shadowNode.nodeType === NODE_TYPE.element) {
1303
- if (parentNode && parentNode.__depth) {
1304
- /*
1305
- We want the depth of the node in the original tree, which can
1306
- change when it's removed from its parent.
1307
- */
1308
- shadowNode.__depth = (shadowNode.__removalCount || 0) + parentNode.__depth + 1;
1309
- } else {
1310
- shadowNode.__depth = 1;
1311
- }
1312
- }
1313
-
1314
- /*
1315
- * Remove an element if nested too deeply to avoid mXSS
1316
- * or if the __depth might have been tampered with
1317
- */
1318
- if (shadowNode.__depth >= MAX_NESTING_DEPTH || shadowNode.__depth < 0 || numberIsNaN(shadowNode.__depth)) {
1319
- _forceRemove(shadowNode);
1320
- }
1321
1287
 
1322
1288
  /* Deep shadow DOM detected */
1323
1289
  if (shadowNode.content instanceof DocumentFragment) {
1324
- shadowNode.content.__depth = shadowNode.__depth;
1325
1290
  _sanitizeShadowDOM(shadowNode.content);
1326
1291
  }
1327
1292
 
@@ -1437,32 +1402,9 @@ function createDOMPurify() {
1437
1402
  if (_sanitizeElements(currentNode)) {
1438
1403
  continue;
1439
1404
  }
1440
- const parentNode = getParentNode(currentNode);
1441
-
1442
- /* Set the nesting depth of an element */
1443
- if (currentNode.nodeType === NODE_TYPE.element) {
1444
- if (parentNode && parentNode.__depth) {
1445
- /*
1446
- We want the depth of the node in the original tree, which can
1447
- change when it's removed from its parent.
1448
- */
1449
- currentNode.__depth = (currentNode.__removalCount || 0) + parentNode.__depth + 1;
1450
- } else {
1451
- currentNode.__depth = 1;
1452
- }
1453
- }
1454
-
1455
- /*
1456
- * Remove an element if nested too deeply to avoid mXSS
1457
- * or if the __depth might have been tampered with
1458
- */
1459
- if (currentNode.__depth >= MAX_NESTING_DEPTH || currentNode.__depth < 0 || numberIsNaN(currentNode.__depth)) {
1460
- _forceRemove(currentNode);
1461
- }
1462
1405
 
1463
1406
  /* Shadow DOM detected, sanitize it */
1464
1407
  if (currentNode.content instanceof DocumentFragment) {
1465
- currentNode.content.__depth = currentNode.__depth;
1466
1408
  _sanitizeShadowDOM(currentNode.content);
1467
1409
  }
1468
1410