dompurify 2.4.0 → 2.4.2

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 2.4.0 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.4.0/LICENSE */
1
+ /*! @license DOMPurify 2.4.2 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.4.2/LICENSE */
2
2
 
3
3
  (function (global, factory) {
4
4
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
@@ -129,6 +129,7 @@
129
129
  var arrayPop = unapply(Array.prototype.pop);
130
130
  var arrayPush = unapply(Array.prototype.push);
131
131
  var stringToLowerCase = unapply(String.prototype.toLowerCase);
132
+ var stringToString = unapply(String.prototype.toString);
132
133
  var stringMatch = unapply(String.prototype.match);
133
134
  var stringReplace = unapply(String.prototype.replace);
134
135
  var stringIndexOf = unapply(String.prototype.indexOf);
@@ -195,7 +196,7 @@
195
196
  var property;
196
197
 
197
198
  for (property in object) {
198
- if (apply(hasOwnProperty, object, [property])) {
199
+ if (apply(hasOwnProperty, object, [property]) === true) {
199
200
  newObject[property] = object[property];
200
201
  }
201
202
  }
@@ -255,6 +256,7 @@
255
256
  var MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
256
257
 
257
258
  var ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
259
+ var TMPLIT_EXPR = seal(/\${[\w\W]*}/gm);
258
260
  var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/); // eslint-disable-line no-useless-escape
259
261
 
260
262
  var ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
@@ -326,7 +328,7 @@
326
328
  */
327
329
 
328
330
 
329
- DOMPurify.version = '2.4.0';
331
+ DOMPurify.version = '2.4.2';
330
332
  /**
331
333
  * Array of elements that DOMPurify removed during sanitation.
332
334
  * Empty if nothing was removed.
@@ -395,6 +397,7 @@
395
397
  DOMPurify.isSupported = typeof getParentNode === 'function' && implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;
396
398
  var MUSTACHE_EXPR$1 = MUSTACHE_EXPR,
397
399
  ERB_EXPR$1 = ERB_EXPR,
400
+ TMPLIT_EXPR$1 = TMPLIT_EXPR,
398
401
  DATA_ATTR$1 = DATA_ATTR,
399
402
  ARIA_ATTR$1 = ARIA_ATTR,
400
403
  IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA,
@@ -534,6 +537,10 @@
534
537
 
535
538
  var NAMESPACE = HTML_NAMESPACE;
536
539
  var IS_EMPTY_INPUT = false;
540
+ /* Allowed XHTML+XML namespaces */
541
+
542
+ var ALLOWED_NAMESPACES = null;
543
+ var DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);
537
544
  /* Parsing of strict XHTML documents */
538
545
 
539
546
  var PARSER_MEDIA_TYPE;
@@ -577,13 +584,12 @@
577
584
  PARSER_MEDIA_TYPE = // eslint-disable-next-line unicorn/prefer-includes
578
585
  SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE; // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
579
586
 
580
- transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? function (x) {
581
- return x;
582
- } : stringToLowerCase;
587
+ transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;
583
588
  /* Set configuration parameters */
584
589
 
585
590
  ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
586
591
  ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
592
+ ALLOWED_NAMESPACES = 'ALLOWED_NAMESPACES' in cfg ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
587
593
  URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), // eslint-disable-line indent
588
594
  cfg.ADD_URI_SAFE_ATTR, // eslint-disable-line indent
589
595
  transformCaseFunc // eslint-disable-line indent
@@ -766,7 +772,7 @@
766
772
 
767
773
  if (!parent || !parent.tagName) {
768
774
  parent = {
769
- namespaceURI: HTML_NAMESPACE,
775
+ namespaceURI: NAMESPACE,
770
776
  tagName: 'template'
771
777
  };
772
778
  }
@@ -774,13 +780,17 @@
774
780
  var tagName = stringToLowerCase(element.tagName);
775
781
  var parentTagName = stringToLowerCase(parent.tagName);
776
782
 
783
+ if (!ALLOWED_NAMESPACES[element.namespaceURI]) {
784
+ return false;
785
+ }
786
+
777
787
  if (element.namespaceURI === SVG_NAMESPACE) {
778
788
  // The only way to switch from HTML namespace to SVG
779
789
  // is via <svg>. If it happens via any other tag, then
780
790
  // it should be killed.
781
791
  if (parent.namespaceURI === HTML_NAMESPACE) {
782
792
  return tagName === 'svg';
783
- } // The only way to switch from MathML to SVG is via
793
+ } // The only way to switch from MathML to SVG is via`
784
794
  // svg if parent is either <annotation-xml> or MathML
785
795
  // text integration points.
786
796
 
@@ -828,9 +838,15 @@
828
838
 
829
839
 
830
840
  return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
841
+ } // For XHTML and XML documents that support custom namespaces
842
+
843
+
844
+ if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) {
845
+ return true;
831
846
  } // The code should never reach this place (this means
832
847
  // that the element somehow got namespace that is not
833
- // HTML, SVG or MathML). Return false just in case.
848
+ // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES).
849
+ // Return false just in case.
834
850
 
835
851
 
836
852
  return false;
@@ -914,7 +930,7 @@
914
930
  leadingWhitespace = matches && matches[0];
915
931
  }
916
932
 
917
- if (PARSER_MEDIA_TYPE === 'application/xhtml+xml') {
933
+ if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && NAMESPACE === HTML_NAMESPACE) {
918
934
  // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)
919
935
  dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
920
936
  }
@@ -937,7 +953,7 @@
937
953
  doc = implementation.createDocument(NAMESPACE, 'template', null);
938
954
 
939
955
  try {
940
- doc.documentElement.innerHTML = IS_EMPTY_INPUT ? '' : dirtyPayload;
956
+ doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;
941
957
  } catch (_) {// Syntax error if dirtyPayload is invalid xml
942
958
  }
943
959
  }
@@ -977,7 +993,7 @@
977
993
 
978
994
 
979
995
  var _isClobbered = function _isClobbered(elm) {
980
- 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');
996
+ 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');
981
997
  };
982
998
  /**
983
999
  * _isNode
@@ -1119,6 +1135,7 @@
1119
1135
  content = currentNode.textContent;
1120
1136
  content = stringReplace(content, MUSTACHE_EXPR$1, ' ');
1121
1137
  content = stringReplace(content, ERB_EXPR$1, ' ');
1138
+ content = stringReplace(content, TMPLIT_EXPR$1, ' ');
1122
1139
 
1123
1140
  if (currentNode.textContent !== content) {
1124
1141
  arrayPush(DOMPurify.removed, {
@@ -1267,6 +1284,7 @@
1267
1284
  if (SAFE_FOR_TEMPLATES) {
1268
1285
  value = stringReplace(value, MUSTACHE_EXPR$1, ' ');
1269
1286
  value = stringReplace(value, ERB_EXPR$1, ' ');
1287
+ value = stringReplace(value, TMPLIT_EXPR$1, ' ');
1270
1288
  }
1271
1289
  /* Is `value` valid for this attribute? */
1272
1290
 
@@ -1562,6 +1580,7 @@
1562
1580
  if (SAFE_FOR_TEMPLATES) {
1563
1581
  serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$1, ' ');
1564
1582
  serializedHTML = stringReplace(serializedHTML, ERB_EXPR$1, ' ');
1583
+ serializedHTML = stringReplace(serializedHTML, TMPLIT_EXPR$1, ' ');
1565
1584
  }
1566
1585
 
1567
1586
  return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;