dompurify 2.2.9 → 2.3.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/dist/purify.es.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! @license DOMPurify | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.2.2/LICENSE */
1
+ /*! @license DOMPurify 2.3.3 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.3.3/LICENSE */
2
2
 
3
3
  function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
4
4
 
@@ -243,7 +243,7 @@ function createDOMPurify() {
243
243
  * Version label, exposed for easier checks
244
244
  * if DOMPurify is up to date or not
245
245
  */
246
- DOMPurify.version = '2.2.9';
246
+ DOMPurify.version = '2.3.3';
247
247
 
248
248
  /**
249
249
  * Array of elements that DOMPurify removed during sanitation.
@@ -301,7 +301,8 @@ function createDOMPurify() {
301
301
  var _document = document,
302
302
  implementation = _document.implementation,
303
303
  createNodeIterator = _document.createNodeIterator,
304
- createDocumentFragment = _document.createDocumentFragment;
304
+ createDocumentFragment = _document.createDocumentFragment,
305
+ getElementsByTagName = _document.getElementsByTagName;
305
306
  var importNode = originalDocument.importNode;
306
307
 
307
308
 
@@ -408,7 +409,8 @@ function createDOMPurify() {
408
409
  var USE_PROFILES = {};
409
410
 
410
411
  /* Tags to ignore content of when KEEP_CONTENT is true */
411
- var FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);
412
+ var FORBID_CONTENTS = null;
413
+ var DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);
412
414
 
413
415
  /* Tags that are safe for data: URIs */
414
416
  var DATA_URI_TAGS = null;
@@ -416,7 +418,7 @@ function createDOMPurify() {
416
418
 
417
419
  /* Attributes safe for values like "javascript:" */
418
420
  var URI_SAFE_ATTRIBUTES = null;
419
- var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'summary', 'title', 'value', 'style', 'xmlns']);
421
+ var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);
420
422
 
421
423
  var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
422
424
  var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
@@ -425,6 +427,12 @@ function createDOMPurify() {
425
427
  var NAMESPACE = HTML_NAMESPACE;
426
428
  var IS_EMPTY_INPUT = false;
427
429
 
430
+ /* Parsing of strict XHTML documents */
431
+ var PARSER_MEDIA_TYPE = void 0;
432
+ var SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];
433
+ var DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
434
+ var transformCaseFunc = void 0;
435
+
428
436
  /* Keep a reference to config to pass to hooks */
429
437
  var CONFIG = null;
430
438
 
@@ -457,6 +465,7 @@ function createDOMPurify() {
457
465
  ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
458
466
  URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR) : DEFAULT_URI_SAFE_ATTRIBUTES;
459
467
  DATA_URI_TAGS = 'ADD_DATA_URI_TAGS' in cfg ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS) : DEFAULT_DATA_URI_TAGS;
468
+ FORBID_CONTENTS = 'FORBID_CONTENTS' in cfg ? addToSet({}, cfg.FORBID_CONTENTS) : DEFAULT_FORBID_CONTENTS;
460
469
  FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};
461
470
  FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};
462
471
  USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
@@ -475,6 +484,16 @@ function createDOMPurify() {
475
484
  IN_PLACE = cfg.IN_PLACE || false; // Default false
476
485
  IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
477
486
  NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
487
+
488
+ PARSER_MEDIA_TYPE =
489
+ // eslint-disable-next-line unicorn/prefer-includes
490
+ SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE;
491
+
492
+ // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
493
+ transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? function (x) {
494
+ return x;
495
+ } : stringToLowerCase;
496
+
478
497
  if (SAFE_FOR_TEMPLATES) {
479
498
  ALLOW_DATA_ATTR = false;
480
499
  }
@@ -532,6 +551,14 @@ function createDOMPurify() {
532
551
  addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);
533
552
  }
534
553
 
554
+ if (cfg.FORBID_CONTENTS) {
555
+ if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
556
+ FORBID_CONTENTS = clone(FORBID_CONTENTS);
557
+ }
558
+
559
+ addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS);
560
+ }
561
+
535
562
  /* Add #text in case KEEP_CONTENT is set to true */
536
563
  if (KEEP_CONTENT) {
537
564
  ALLOWED_TAGS['#text'] = true;
@@ -735,6 +762,11 @@ function createDOMPurify() {
735
762
  leadingWhitespace = matches && matches[0];
736
763
  }
737
764
 
765
+ if (PARSER_MEDIA_TYPE === 'application/xhtml+xml') {
766
+ // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)
767
+ dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
768
+ }
769
+
738
770
  var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
739
771
  /*
740
772
  * Use the DOMParser API by default, fallback later if needs be
@@ -742,7 +774,7 @@ function createDOMPurify() {
742
774
  */
743
775
  if (NAMESPACE === HTML_NAMESPACE) {
744
776
  try {
745
- doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
777
+ doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
746
778
  } catch (_) {}
747
779
  }
748
780
 
@@ -763,6 +795,10 @@ function createDOMPurify() {
763
795
  }
764
796
 
765
797
  /* Work on whole document or just its body */
798
+ if (NAMESPACE === HTML_NAMESPACE) {
799
+ return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
800
+ }
801
+
766
802
  return WHOLE_DOCUMENT ? doc.documentElement : body;
767
803
  };
768
804
 
@@ -851,7 +887,7 @@ function createDOMPurify() {
851
887
  }
852
888
 
853
889
  /* Now let's check the element's type and name */
854
- var tagName = stringToLowerCase(currentNode.nodeName);
890
+ var tagName = transformCaseFunc(currentNode.nodeName);
855
891
 
856
892
  /* Execute a hook if present */
857
893
  _executeHook('uponSanitizeElement', currentNode, {
@@ -865,6 +901,12 @@ function createDOMPurify() {
865
901
  return true;
866
902
  }
867
903
 
904
+ /* Mitigate a problem with templates inside select */
905
+ if (tagName === 'select' && regExpTest(/<template/i, currentNode.innerHTML)) {
906
+ _forceRemove(currentNode);
907
+ return true;
908
+ }
909
+
868
910
  /* Remove element if anything forbids its presence */
869
911
  if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
870
912
  /* Keep content except for bad-listed elements */
@@ -933,7 +975,7 @@ function createDOMPurify() {
933
975
  (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
934
976
  XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
935
977
  We don't need to check the value; it's always URI safe. */
936
- if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$$1, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$$1, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
978
+ if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$$1, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$$1, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
937
979
  return false;
938
980
 
939
981
  /* Check value is safe. First, is attr inert? If so, is safe */
@@ -986,7 +1028,7 @@ function createDOMPurify() {
986
1028
  namespaceURI = _attr.namespaceURI;
987
1029
 
988
1030
  value = stringTrim(attr.value);
989
- lcName = stringToLowerCase(name);
1031
+ lcName = transformCaseFunc(name);
990
1032
 
991
1033
  /* Execute a hook if present */
992
1034
  hookEvent.attrName = lcName;
@@ -1021,7 +1063,7 @@ function createDOMPurify() {
1021
1063
  }
1022
1064
 
1023
1065
  /* Is `value` valid for this attribute? */
1024
- var lcTag = currentNode.nodeName.toLowerCase();
1066
+ var lcTag = transformCaseFunc(currentNode.nodeName);
1025
1067
  if (!_isValidAttribute(lcTag, lcName, value)) {
1026
1068
  continue;
1027
1069
  }
@@ -1284,8 +1326,8 @@ function createDOMPurify() {
1284
1326
  _parseConfig({});
1285
1327
  }
1286
1328
 
1287
- var lcTag = stringToLowerCase(tag);
1288
- var lcName = stringToLowerCase(attr);
1329
+ var lcTag = transformCaseFunc(tag);
1330
+ var lcName = transformCaseFunc(attr);
1289
1331
  return _isValidAttribute(lcTag, lcName, value);
1290
1332
  };
1291
1333