dompurify 3.2.5 → 3.2.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.
package/dist/purify.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! @license DOMPurify 3.2.5 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.5/LICENSE */
1
+ /*! @license DOMPurify 3.2.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.2.6/LICENSE */
2
2
 
3
3
  (function (global, factory) {
4
4
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
@@ -208,7 +208,7 @@
208
208
  const TMPLIT_EXPR = seal(/\$\{[\w\W]*/gm); // eslint-disable-line unicorn/better-regex
209
209
  const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); // eslint-disable-line no-useless-escape
210
210
  const ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
211
- 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
211
+ const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape
212
212
  );
213
213
  const IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
214
214
  const ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex
@@ -305,7 +305,7 @@
305
305
  function createDOMPurify() {
306
306
  let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
307
307
  const DOMPurify = root => createDOMPurify(root);
308
- DOMPurify.version = '3.2.5';
308
+ DOMPurify.version = '3.2.6';
309
309
  DOMPurify.removed = [];
310
310
  if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
311
311
  // Not running in a browser, provide a factory function
@@ -544,8 +544,8 @@
544
544
  URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;
545
545
  DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;
546
546
  FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
547
- FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : {};
548
- FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : {};
547
+ FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone({});
548
+ FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});
549
549
  USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES : false;
550
550
  ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
551
551
  ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
@@ -910,7 +910,7 @@
910
910
  allowedTags: ALLOWED_TAGS
911
911
  });
912
912
  /* Detect mXSS attempts abusing namespace confusion */
913
- if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\w!]/g, currentNode.innerHTML) && regExpTest(/<[/\w!]/g, currentNode.textContent)) {
913
+ if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\w!]/g, currentNode.innerHTML) && regExpTest(/<[/\w!]/g, currentNode.textContent)) {
914
914
  _forceRemove(currentNode);
915
915
  return true;
916
916
  }
@@ -1062,7 +1062,8 @@
1062
1062
  value: attrValue
1063
1063
  } = attr;
1064
1064
  const lcName = transformCaseFunc(name);
1065
- let value = name === 'value' ? attrValue : stringTrim(attrValue);
1065
+ const initValue = attrValue;
1066
+ let value = name === 'value' ? initValue : stringTrim(initValue);
1066
1067
  /* Execute a hook if present */
1067
1068
  hookEvent.attrName = lcName;
1068
1069
  hookEvent.attrValue = value;
@@ -1088,10 +1089,9 @@
1088
1089
  if (hookEvent.forceKeepAttr) {
1089
1090
  continue;
1090
1091
  }
1091
- /* Remove attribute */
1092
- _removeAttribute(name, currentNode);
1093
1092
  /* Did the hooks approve of the attribute? */
1094
1093
  if (!hookEvent.keepAttr) {
1094
+ _removeAttribute(name, currentNode);
1095
1095
  continue;
1096
1096
  }
1097
1097
  /* Work around a security issue in jQuery 3.0 */
@@ -1108,6 +1108,7 @@
1108
1108
  /* Is `value` valid for this attribute? */
1109
1109
  const lcTag = transformCaseFunc(currentNode.nodeName);
1110
1110
  if (!_isValidAttribute(lcTag, lcName, value)) {
1111
+ _removeAttribute(name, currentNode);
1111
1112
  continue;
1112
1113
  }
1113
1114
  /* Handle attributes that require Trusted Types */
@@ -1128,19 +1129,23 @@
1128
1129
  }
1129
1130
  }
1130
1131
  /* Handle invalid data-* attribute set by try-catching it */
1131
- try {
1132
- if (namespaceURI) {
1133
- currentNode.setAttributeNS(namespaceURI, name, value);
1134
- } else {
1135
- /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
1136
- currentNode.setAttribute(name, value);
1137
- }
1138
- if (_isClobbered(currentNode)) {
1139
- _forceRemove(currentNode);
1140
- } else {
1141
- arrayPop(DOMPurify.removed);
1132
+ if (value !== initValue) {
1133
+ try {
1134
+ if (namespaceURI) {
1135
+ currentNode.setAttributeNS(namespaceURI, name, value);
1136
+ } else {
1137
+ /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
1138
+ currentNode.setAttribute(name, value);
1139
+ }
1140
+ if (_isClobbered(currentNode)) {
1141
+ _forceRemove(currentNode);
1142
+ } else {
1143
+ arrayPop(DOMPurify.removed);
1144
+ }
1145
+ } catch (_) {
1146
+ _removeAttribute(name, currentNode);
1142
1147
  }
1143
- } catch (_) {}
1148
+ }
1144
1149
  }
1145
1150
  /* Execute a hook if present */
1146
1151
  _executeHooks(hooks.afterSanitizeAttributes, currentNode, null);