dompurify 2.4.0 → 2.4.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/README.md CHANGED
@@ -6,7 +6,7 @@
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 2.4.0.
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 2.4.1.
10
10
 
11
11
  DOMPurify is written in JavaScript and works in all modern browsers (Safari (10+), Opera (15+), Internet Explorer (10+), Edge, Firefox and Chrome - as well as almost anything else using Blink or WebKit). It doesn't break on MSIE6 or other legacy browsers. It either uses [a fall-back](#what-about-older-browsers-like-msie8) or simply does nothing.
12
12
 
@@ -55,6 +55,10 @@ Note that by default, we permit HTML, SVG **and** MathML. If you only need HTML,
55
55
  let clean = DOMPurify.sanitize(dirty, { USE_PROFILES: { html: true } });
56
56
  ```
57
57
 
58
+ ### Where are the TypeScript type definitions?
59
+
60
+ They can be found here: [@types/dompurify](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/dompurify)
61
+
58
62
  ### Is there any foot-gun potential?
59
63
 
60
64
  Well, please note, if you _first_ sanitize HTML and then modify it _afterwards_, you might easily **void the effects of sanitization**. If you feed the sanitized markup to another library _after_ sanitization, please be certain that the library doesn't mess around with the HTML on its own.
@@ -163,7 +167,7 @@ Yes. The included default configuration values are pretty good already - but you
163
167
  * General settings
164
168
  */
165
169
 
166
- // strip {{ ... }} and <% ... %> to make output safe for template systems
170
+ // strip {{ ... }}, ${ ... } and <% ... %> to make output safe for template systems
167
171
  // be careful please, this mode is not recommended for production usage.
168
172
  // allowing template parsing in user-controlled HTML is not advised at all.
169
173
  // only use this mode if there is really no alternative.
@@ -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.1 | (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.1/LICENSE */
2
2
 
3
3
  'use strict';
4
4
 
@@ -125,6 +125,7 @@ var arrayForEach = unapply(Array.prototype.forEach);
125
125
  var arrayPop = unapply(Array.prototype.pop);
126
126
  var arrayPush = unapply(Array.prototype.push);
127
127
  var stringToLowerCase = unapply(String.prototype.toLowerCase);
128
+ var stringToString = unapply(String.prototype.toString);
128
129
  var stringMatch = unapply(String.prototype.match);
129
130
  var stringReplace = unapply(String.prototype.replace);
130
131
  var stringIndexOf = unapply(String.prototype.indexOf);
@@ -251,6 +252,7 @@ var xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xli
251
252
  var MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
252
253
 
253
254
  var ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
255
+ var TMPLIT_EXPR = seal(/\${[\w\W]*}/gm);
254
256
  var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/); // eslint-disable-line no-useless-escape
255
257
 
256
258
  var ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
@@ -322,7 +324,7 @@ function createDOMPurify() {
322
324
  */
323
325
 
324
326
 
325
- DOMPurify.version = '2.4.0';
327
+ DOMPurify.version = '2.4.1';
326
328
  /**
327
329
  * Array of elements that DOMPurify removed during sanitation.
328
330
  * Empty if nothing was removed.
@@ -391,6 +393,7 @@ function createDOMPurify() {
391
393
  DOMPurify.isSupported = typeof getParentNode === 'function' && implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;
392
394
  var MUSTACHE_EXPR$1 = MUSTACHE_EXPR,
393
395
  ERB_EXPR$1 = ERB_EXPR,
396
+ TMPLIT_EXPR$1 = TMPLIT_EXPR,
394
397
  DATA_ATTR$1 = DATA_ATTR,
395
398
  ARIA_ATTR$1 = ARIA_ATTR,
396
399
  IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA,
@@ -530,6 +533,10 @@ function createDOMPurify() {
530
533
 
531
534
  var NAMESPACE = HTML_NAMESPACE;
532
535
  var IS_EMPTY_INPUT = false;
536
+ /* Allowed XHTML+XML namespaces */
537
+
538
+ var ALLOWED_NAMESPACES = null;
539
+ var DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);
533
540
  /* Parsing of strict XHTML documents */
534
541
 
535
542
  var PARSER_MEDIA_TYPE;
@@ -573,13 +580,12 @@ function createDOMPurify() {
573
580
  PARSER_MEDIA_TYPE = // eslint-disable-next-line unicorn/prefer-includes
574
581
  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.
575
582
 
576
- transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? function (x) {
577
- return x;
578
- } : stringToLowerCase;
583
+ transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;
579
584
  /* Set configuration parameters */
580
585
 
581
586
  ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
582
587
  ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
588
+ ALLOWED_NAMESPACES = 'ALLOWED_NAMESPACES' in cfg ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
583
589
  URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), // eslint-disable-line indent
584
590
  cfg.ADD_URI_SAFE_ATTR, // eslint-disable-line indent
585
591
  transformCaseFunc // eslint-disable-line indent
@@ -762,7 +768,7 @@ function createDOMPurify() {
762
768
 
763
769
  if (!parent || !parent.tagName) {
764
770
  parent = {
765
- namespaceURI: HTML_NAMESPACE,
771
+ namespaceURI: NAMESPACE,
766
772
  tagName: 'template'
767
773
  };
768
774
  }
@@ -770,13 +776,17 @@ function createDOMPurify() {
770
776
  var tagName = stringToLowerCase(element.tagName);
771
777
  var parentTagName = stringToLowerCase(parent.tagName);
772
778
 
779
+ if (!ALLOWED_NAMESPACES[element.namespaceURI]) {
780
+ return false;
781
+ }
782
+
773
783
  if (element.namespaceURI === SVG_NAMESPACE) {
774
784
  // The only way to switch from HTML namespace to SVG
775
785
  // is via <svg>. If it happens via any other tag, then
776
786
  // it should be killed.
777
787
  if (parent.namespaceURI === HTML_NAMESPACE) {
778
788
  return tagName === 'svg';
779
- } // The only way to switch from MathML to SVG is via
789
+ } // The only way to switch from MathML to SVG is via`
780
790
  // svg if parent is either <annotation-xml> or MathML
781
791
  // text integration points.
782
792
 
@@ -824,9 +834,15 @@ function createDOMPurify() {
824
834
 
825
835
 
826
836
  return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
837
+ } // For XHTML and XML documents that support custom namespaces
838
+
839
+
840
+ if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) {
841
+ return true;
827
842
  } // The code should never reach this place (this means
828
843
  // that the element somehow got namespace that is not
829
- // HTML, SVG or MathML). Return false just in case.
844
+ // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES).
845
+ // Return false just in case.
830
846
 
831
847
 
832
848
  return false;
@@ -910,7 +926,7 @@ function createDOMPurify() {
910
926
  leadingWhitespace = matches && matches[0];
911
927
  }
912
928
 
913
- if (PARSER_MEDIA_TYPE === 'application/xhtml+xml') {
929
+ if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && NAMESPACE === HTML_NAMESPACE) {
914
930
  // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)
915
931
  dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
916
932
  }
@@ -973,7 +989,7 @@ function createDOMPurify() {
973
989
 
974
990
 
975
991
  var _isClobbered = function _isClobbered(elm) {
976
- 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');
992
+ 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');
977
993
  };
978
994
  /**
979
995
  * _isNode
@@ -1115,6 +1131,7 @@ function createDOMPurify() {
1115
1131
  content = currentNode.textContent;
1116
1132
  content = stringReplace(content, MUSTACHE_EXPR$1, ' ');
1117
1133
  content = stringReplace(content, ERB_EXPR$1, ' ');
1134
+ content = stringReplace(content, TMPLIT_EXPR$1, ' ');
1118
1135
 
1119
1136
  if (currentNode.textContent !== content) {
1120
1137
  arrayPush(DOMPurify.removed, {
@@ -1263,6 +1280,7 @@ function createDOMPurify() {
1263
1280
  if (SAFE_FOR_TEMPLATES) {
1264
1281
  value = stringReplace(value, MUSTACHE_EXPR$1, ' ');
1265
1282
  value = stringReplace(value, ERB_EXPR$1, ' ');
1283
+ value = stringReplace(value, TMPLIT_EXPR$1, ' ');
1266
1284
  }
1267
1285
  /* Is `value` valid for this attribute? */
1268
1286
 
@@ -1558,6 +1576,7 @@ function createDOMPurify() {
1558
1576
  if (SAFE_FOR_TEMPLATES) {
1559
1577
  serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$1, ' ');
1560
1578
  serializedHTML = stringReplace(serializedHTML, ERB_EXPR$1, ' ');
1579
+ serializedHTML = stringReplace(serializedHTML, TMPLIT_EXPR$1, ' ');
1561
1580
  }
1562
1581
 
1563
1582
  return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;