dompurify 3.1.2 → 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 CHANGED
@@ -6,11 +6,11 @@
6
6
 
7
7
  DOMPurify is a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG.
8
8
 
9
- It's also very simple to use and get started with. DOMPurify was [started in February 2014](https://github.com/cure53/DOMPurify/commit/a630922616927373485e0e787ab19e73e3691b2b) and, meanwhile, has reached version **v3.1.2**.
9
+ It's also very simple to use and get started with. DOMPurify was [started in February 2014](https://github.com/cure53/DOMPurify/commit/a630922616927373485e0e787ab19e73e3691b2b) and, meanwhile, has reached version **v3.1.3**.
10
10
 
11
11
  DOMPurify is written in JavaScript and works in all modern browsers (Safari (10+), Opera (15+), Edge, Firefox and Chrome - as well as almost anything else using Blink, Gecko or WebKit). It doesn't break on MSIE or other legacy browsers. It simply does nothing.
12
12
 
13
- **Note that [DOMPurify v2.5.2](https://github.com/cure53/DOMPurify/releases/tag/2.5.2) is the latest version supporting MSIE. For important security updates compatible with MSIE, please use the [2.x branch](https://github.com/cure53/DOMPurify/tree/2.x).**
13
+ **Note that [DOMPurify v2.5.3](https://github.com/cure53/DOMPurify/releases/tag/2.5.3) is the latest version supporting MSIE. For important security updates compatible with MSIE, please use the [2.x branch](https://github.com/cure53/DOMPurify/tree/2.x).**
14
14
 
15
15
  Our automated tests cover [19 different browsers](https://github.com/cure53/DOMPurify/blob/main/test/karma.custom-launchers.config.js#L5) right now, more to come. We also cover Node.js v16.x, v17.x, v18.x and v19.x, running DOMPurify on [jsdom](https://github.com/jsdom/jsdom). Older Node versions are known to work as well, but hey... no guarantees.
16
16
 
@@ -424,7 +424,7 @@ Feature releases will not be announced to this list.
424
424
 
425
425
  Many people helped and help DOMPurify become what it is and need to be acknowledged here!
426
426
 
427
- [icesfont ❤️](https://github.com/icesfont) [dcramer 💸](https://github.com/dcramer), [JGraph 💸](https://github.com/jgraph), [baekilda 💸](https://github.com/baekilda), [Healthchecks 💸](https://github.com/healthchecks), [Sentry 💸](https://github.com/getsentry), [jarrodldavis 💸](https://github.com/jarrodldavis), [CynegeticIO](https://github.com/CynegeticIO), [ssi02014 ❤️](https://github.com/ssi02014), [kevin_mizu](https://twitter.com/kevin_mizu), [GrantGryczan](https://github.com/GrantGryczan), [Lowdefy](https://twitter.com/lowdefy), [granlem](https://twitter.com/MaximeVeit), [oreoshake](https://github.com/oreoshake), [tdeekens ❤️](https://github.com/tdeekens), [peernohell ❤️](https://github.com/peernohell), [is2ei](https://github.com/is2ei), [SoheilKhodayari](https://github.com/SoheilKhodayari), [franktopel](https://github.com/franktopel), [NateScarlet](https://github.com/NateScarlet), [neilj](https://github.com/neilj), [fhemberger](https://github.com/fhemberger), [Joris-van-der-Wel](https://github.com/Joris-van-der-Wel), [ydaniv](https://github.com/ydaniv), [terjanq](https://twitter.com/terjanq), [filedescriptor](https://github.com/filedescriptor), [ConradIrwin](https://github.com/ConradIrwin), [gibson042](https://github.com/gibson042), [choumx](https://github.com/choumx), [0xSobky](https://github.com/0xSobky), [styfle](https://github.com/styfle), [koto](https://github.com/koto), [tlau88](https://github.com/tlau88), [strugee](https://github.com/strugee), [oparoz](https://github.com/oparoz), [mathiasbynens](https://github.com/mathiasbynens), [edg2s](https://github.com/edg2s), [dnkolegov](https://github.com/dnkolegov), [dhardtke](https://github.com/dhardtke), [wirehead](https://github.com/wirehead), [thorn0](https://github.com/thorn0), [styu](https://github.com/styu), [mozfreddyb](https://github.com/mozfreddyb), [mikesamuel](https://github.com/mikesamuel), [jorangreef](https://github.com/jorangreef), [jimmyhchan](https://github.com/jimmyhchan), [jameydeorio](https://github.com/jameydeorio), [jameskraus](https://github.com/jameskraus), [hyderali](https://github.com/hyderali), [hansottowirtz](https://github.com/hansottowirtz), [hackvertor](https://github.com/hackvertor), [freddyb](https://github.com/freddyb), [flavorjones](https://github.com/flavorjones), [djfarrelly](https://github.com/djfarrelly), [devd](https://github.com/devd), [camerondunford](https://github.com/camerondunford), [buu700](https://github.com/buu700), [buildog](https://github.com/buildog), [alabiaga](https://github.com/alabiaga), [Vector919](https://github.com/Vector919), [Robbert](https://github.com/Robbert), [GreLI](https://github.com/GreLI), [FuzzySockets](https://github.com/FuzzySockets), [ArtemBernatskyy](https://github.com/ArtemBernatskyy), [@garethheyes](https://twitter.com/garethheyes), [@shafigullin](https://twitter.com/shafigullin), [@mmrupp](https://twitter.com/mmrupp), [@irsdl](https://twitter.com/irsdl),[ShikariSenpai](https://github.com/ShikariSenpai), [ansjdnakjdnajkd](https://github.com/ansjdnakjdnajkd), [@asutherland](https://twitter.com/asutherland), [@mathias](https://twitter.com/mathias), [@cgvwzq](https://twitter.com/cgvwzq), [@robbertatwork](https://twitter.com/robbertatwork), [@giutro](https://twitter.com/giutro), [@CmdEngineer\_](https://twitter.com/CmdEngineer_), [@avr4mit](https://twitter.com/avr4mit) and especially [@securitymb ❤️](https://twitter.com/securitymb) & [@masatokinugawa ❤️](https://twitter.com/masatokinugawa)
427
+ [hash_kitten ❤️](https://twitter.com/hash_kitten), [kevin_mizu ❤️](https://twitter.com/kevin_mizu), [icesfont ❤️](https://github.com/icesfont) [dcramer 💸](https://github.com/dcramer), [JGraph 💸](https://github.com/jgraph), [baekilda 💸](https://github.com/baekilda), [Healthchecks 💸](https://github.com/healthchecks), [Sentry 💸](https://github.com/getsentry), [jarrodldavis 💸](https://github.com/jarrodldavis), [CynegeticIO](https://github.com/CynegeticIO), [ssi02014 ❤️](https://github.com/ssi02014), [GrantGryczan](https://github.com/GrantGryczan), [Lowdefy](https://twitter.com/lowdefy), [granlem](https://twitter.com/MaximeVeit), [oreoshake](https://github.com/oreoshake), [tdeekens ❤️](https://github.com/tdeekens), [peernohell ❤️](https://github.com/peernohell), [is2ei](https://github.com/is2ei), [SoheilKhodayari](https://github.com/SoheilKhodayari), [franktopel](https://github.com/franktopel), [NateScarlet](https://github.com/NateScarlet), [neilj](https://github.com/neilj), [fhemberger](https://github.com/fhemberger), [Joris-van-der-Wel](https://github.com/Joris-van-der-Wel), [ydaniv](https://github.com/ydaniv), [terjanq](https://twitter.com/terjanq), [filedescriptor](https://github.com/filedescriptor), [ConradIrwin](https://github.com/ConradIrwin), [gibson042](https://github.com/gibson042), [choumx](https://github.com/choumx), [0xSobky](https://github.com/0xSobky), [styfle](https://github.com/styfle), [koto](https://github.com/koto), [tlau88](https://github.com/tlau88), [strugee](https://github.com/strugee), [oparoz](https://github.com/oparoz), [mathiasbynens](https://github.com/mathiasbynens), [edg2s](https://github.com/edg2s), [dnkolegov](https://github.com/dnkolegov), [dhardtke](https://github.com/dhardtke), [wirehead](https://github.com/wirehead), [thorn0](https://github.com/thorn0), [styu](https://github.com/styu), [mozfreddyb](https://github.com/mozfreddyb), [mikesamuel](https://github.com/mikesamuel), [jorangreef](https://github.com/jorangreef), [jimmyhchan](https://github.com/jimmyhchan), [jameydeorio](https://github.com/jameydeorio), [jameskraus](https://github.com/jameskraus), [hyderali](https://github.com/hyderali), [hansottowirtz](https://github.com/hansottowirtz), [hackvertor](https://github.com/hackvertor), [freddyb](https://github.com/freddyb), [flavorjones](https://github.com/flavorjones), [djfarrelly](https://github.com/djfarrelly), [devd](https://github.com/devd), [camerondunford](https://github.com/camerondunford), [buu700](https://github.com/buu700), [buildog](https://github.com/buildog), [alabiaga](https://github.com/alabiaga), [Vector919](https://github.com/Vector919), [Robbert](https://github.com/Robbert), [GreLI](https://github.com/GreLI), [FuzzySockets](https://github.com/FuzzySockets), [ArtemBernatskyy](https://github.com/ArtemBernatskyy), [@garethheyes](https://twitter.com/garethheyes), [@shafigullin](https://twitter.com/shafigullin), [@mmrupp](https://twitter.com/mmrupp), [@irsdl](https://twitter.com/irsdl),[ShikariSenpai](https://github.com/ShikariSenpai), [ansjdnakjdnajkd](https://github.com/ansjdnakjdnajkd), [@asutherland](https://twitter.com/asutherland), [@mathias](https://twitter.com/mathias), [@cgvwzq](https://twitter.com/cgvwzq), [@robbertatwork](https://twitter.com/robbertatwork), [@giutro](https://twitter.com/giutro), [@CmdEngineer\_](https://twitter.com/CmdEngineer_), [@avr4mit](https://twitter.com/avr4mit) and especially [@securitymb ❤️](https://twitter.com/securitymb) & [@masatokinugawa ❤️](https://twitter.com/masatokinugawa)
428
428
 
429
429
  ## Testing powered by
430
430
 
@@ -1,4 +1,4 @@
1
- /*! @license DOMPurify 3.1.2 | (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.2/LICENSE */
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
  'use strict';
4
4
 
@@ -50,6 +50,7 @@ const stringTrim = unapply(String.prototype.trim);
50
50
  const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
51
51
  const regExpTest = unapply(RegExp.prototype.test);
52
52
  const typeErrorCreate = unconstruct(TypeError);
53
+ const numberIsNaN = unapply(Number.isNaN);
53
54
 
54
55
  /**
55
56
  * Creates a new function that calls the given function with a specified thisArg and arguments.
@@ -233,6 +234,24 @@ var EXPRESSIONS = /*#__PURE__*/Object.freeze({
233
234
  CUSTOM_ELEMENT: CUSTOM_ELEMENT
234
235
  });
235
236
 
237
+ // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
238
+ const NODE_TYPE = {
239
+ element: 1,
240
+ attribute: 2,
241
+ text: 3,
242
+ cdataSection: 4,
243
+ entityReference: 5,
244
+ // Deprecated
245
+ entityNode: 6,
246
+ // Deprecated
247
+ progressingInstruction: 7,
248
+ comment: 8,
249
+ document: 9,
250
+ documentType: 10,
251
+ documentFragment: 11,
252
+ notation: 12 // Deprecated
253
+ };
254
+
236
255
  const getGlobal = function getGlobal() {
237
256
  return typeof window === 'undefined' ? null : window;
238
257
  };
@@ -284,14 +303,14 @@ function createDOMPurify() {
284
303
  * Version label, exposed for easier checks
285
304
  * if DOMPurify is up to date or not
286
305
  */
287
- DOMPurify.version = '3.1.2';
306
+ DOMPurify.version = '3.1.3';
288
307
 
289
308
  /**
290
309
  * Array of elements that DOMPurify removed during sanitation.
291
310
  * Empty if nothing was removed.
292
311
  */
293
312
  DOMPurify.removed = [];
294
- if (!window || !window.document || window.document.nodeType !== 9) {
313
+ if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document) {
295
314
  // Not running in a browser, provide a factory function
296
315
  // so that you can pass your own Window
297
316
  DOMPurify.isSupported = false;
@@ -1002,13 +1021,13 @@ function createDOMPurify() {
1002
1021
  }
1003
1022
 
1004
1023
  /* Remove any ocurrence of processing instructions */
1005
- if (currentNode.nodeType === 7) {
1024
+ if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {
1006
1025
  _forceRemove(currentNode);
1007
1026
  return true;
1008
1027
  }
1009
1028
 
1010
1029
  /* Remove any kind of possibly harmful comments */
1011
- if (SAFE_FOR_XML && currentNode.nodeType === 8 && regExpTest(/<[/\w]/g, currentNode.data)) {
1030
+ if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(/<[/\w]/g, currentNode.data)) {
1012
1031
  _forceRemove(currentNode);
1013
1032
  return true;
1014
1033
  }
@@ -1055,7 +1074,7 @@ function createDOMPurify() {
1055
1074
  }
1056
1075
 
1057
1076
  /* Sanitize element content to be template-safe */
1058
- if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
1077
+ if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {
1059
1078
  /* Get the element's text content */
1060
1079
  content = currentNode.textContent;
1061
1080
  arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
@@ -1085,7 +1104,7 @@ function createDOMPurify() {
1085
1104
  // eslint-disable-next-line complexity
1086
1105
  const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
1087
1106
  /* Make sure attribute cannot clobber */
1088
- if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
1107
+ if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement || value === '__depth' || value === '__removalCount')) {
1089
1108
  return false;
1090
1109
  }
1091
1110
 
@@ -1189,6 +1208,12 @@ function createDOMPurify() {
1189
1208
  continue;
1190
1209
  }
1191
1210
 
1211
+ /* Work around a security issue with comments inside attributes */
1212
+ if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|title)/i, value)) {
1213
+ _removeAttribute(name, currentNode);
1214
+ continue;
1215
+ }
1216
+
1192
1217
  /* Sanitize attribute content to be template-safe */
1193
1218
  if (SAFE_FOR_TEMPLATES) {
1194
1219
  arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
@@ -1239,7 +1264,11 @@ function createDOMPurify() {
1239
1264
  /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
1240
1265
  currentNode.setAttribute(name, value);
1241
1266
  }
1242
- arrayPop(DOMPurify.removed);
1267
+ if (_isClobbered(currentNode)) {
1268
+ _forceRemove(currentNode);
1269
+ } else {
1270
+ arrayPop(DOMPurify.removed);
1271
+ }
1243
1272
  } catch (_) {}
1244
1273
  }
1245
1274
 
@@ -1269,7 +1298,7 @@ function createDOMPurify() {
1269
1298
  const parentNode = getParentNode(shadowNode);
1270
1299
 
1271
1300
  /* Set the nesting depth of an element */
1272
- if (shadowNode.nodeType === 1) {
1301
+ if (shadowNode.nodeType === NODE_TYPE.element) {
1273
1302
  if (parentNode && parentNode.__depth) {
1274
1303
  /*
1275
1304
  We want the depth of the node in the original tree, which can
@@ -1281,8 +1310,11 @@ function createDOMPurify() {
1281
1310
  }
1282
1311
  }
1283
1312
 
1284
- /* Remove an element if nested too deeply to avoid mXSS */
1285
- if (shadowNode.__depth >= MAX_NESTING_DEPTH) {
1313
+ /*
1314
+ * Remove an element if nested too deeply to avoid mXSS
1315
+ * or if the __depth might have been tampered with
1316
+ */
1317
+ if (shadowNode.__depth >= MAX_NESTING_DEPTH || shadowNode.__depth < 0 || numberIsNaN(shadowNode.__depth)) {
1286
1318
  _forceRemove(shadowNode);
1287
1319
  }
1288
1320
 
@@ -1364,7 +1396,7 @@ function createDOMPurify() {
1364
1396
  elements being stripped by the parser */
1365
1397
  body = _initDocument('<!---->');
1366
1398
  importedNode = body.ownerDocument.importNode(dirty, true);
1367
- if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {
1399
+ if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === 'BODY') {
1368
1400
  /* Node is already a body, use as is */
1369
1401
  body = importedNode;
1370
1402
  } else if (importedNode.nodeName === 'HTML') {
@@ -1407,7 +1439,7 @@ function createDOMPurify() {
1407
1439
  const parentNode = getParentNode(currentNode);
1408
1440
 
1409
1441
  /* Set the nesting depth of an element */
1410
- if (currentNode.nodeType === 1) {
1442
+ if (currentNode.nodeType === NODE_TYPE.element) {
1411
1443
  if (parentNode && parentNode.__depth) {
1412
1444
  /*
1413
1445
  We want the depth of the node in the original tree, which can
@@ -1419,8 +1451,11 @@ function createDOMPurify() {
1419
1451
  }
1420
1452
  }
1421
1453
 
1422
- /* Remove an element if nested too deeply to avoid mXSS */
1423
- if (currentNode.__depth >= MAX_NESTING_DEPTH) {
1454
+ /*
1455
+ * Remove an element if nested too deeply to avoid mXSS
1456
+ * or if the __depth might have been tampered with
1457
+ */
1458
+ if (currentNode.__depth >= MAX_NESTING_DEPTH || currentNode.__depth < 0 || numberIsNaN(currentNode.__depth)) {
1424
1459
  _forceRemove(currentNode);
1425
1460
  }
1426
1461