dompurify 3.4.6 → 3.4.8
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/LICENSE-MPL +373 -0
- package/README.md +19 -2
- package/dist/purify.cjs.d.ts +2 -2
- package/dist/purify.cjs.js +116 -69
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.d.mts +2 -2
- package/dist/purify.es.mjs +116 -69
- package/dist/purify.es.mjs.map +1 -1
- package/dist/purify.js +116 -69
- package/dist/purify.js.map +1 -1
- package/dist/purify.min.js +2 -2
- package/dist/purify.min.js.map +1 -1
- package/package.json +15 -14
- package/src/config.ts +1 -1
- package/src/purify.ts +141 -66
package/dist/purify.cjs.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @license DOMPurify 3.4.
|
|
1
|
+
/*! @license DOMPurify 3.4.8 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.8/LICENSE */
|
|
2
2
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
@@ -405,7 +405,7 @@ const _createHooksMap = function _createHooksMap() {
|
|
|
405
405
|
function createDOMPurify() {
|
|
406
406
|
let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
|
|
407
407
|
const DOMPurify = root => createDOMPurify(root);
|
|
408
|
-
DOMPurify.version = '3.4.
|
|
408
|
+
DOMPurify.version = '3.4.8';
|
|
409
409
|
DOMPurify.removed = [];
|
|
410
410
|
if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
|
|
411
411
|
// Not running in a browser, provide a factory function
|
|
@@ -450,6 +450,23 @@ function createDOMPurify() {
|
|
|
450
450
|
}
|
|
451
451
|
let trustedTypesPolicy;
|
|
452
452
|
let emptyHTML = '';
|
|
453
|
+
// Tracks whether we are already inside a call to the configured Trusted Types
|
|
454
|
+
// policy's `createHTML`. If the supplied `TRUSTED_TYPES_POLICY.createHTML`
|
|
455
|
+
// itself calls `DOMPurify.sanitize` (the cause of #1422), `sanitize` would
|
|
456
|
+
// re-enter the policy and recurse until the stack overflows. We detect that
|
|
457
|
+
// re-entry and throw a clear, actionable error instead.
|
|
458
|
+
let IN_POLICY_CREATE_HTML = 0;
|
|
459
|
+
const _createTrustedHTML = function _createTrustedHTML(html) {
|
|
460
|
+
if (IN_POLICY_CREATE_HTML > 0) {
|
|
461
|
+
throw typeErrorCreate('The configured TRUSTED_TYPES_POLICY.createHTML must not call ' + 'DOMPurify.sanitize, as that causes infinite recursion. Do not pass ' + 'a policy whose createHTML wraps DOMPurify as TRUSTED_TYPES_POLICY; ' + 'see the "DOMPurify and Trusted Types" section of the README.');
|
|
462
|
+
}
|
|
463
|
+
IN_POLICY_CREATE_HTML++;
|
|
464
|
+
try {
|
|
465
|
+
return trustedTypesPolicy.createHTML(html);
|
|
466
|
+
} finally {
|
|
467
|
+
IN_POLICY_CREATE_HTML--;
|
|
468
|
+
}
|
|
469
|
+
};
|
|
453
470
|
const _document = document,
|
|
454
471
|
implementation = _document.implementation,
|
|
455
472
|
createNodeIterator = _document.createNodeIterator,
|
|
@@ -777,19 +794,47 @@ function createDOMPurify() {
|
|
|
777
794
|
throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');
|
|
778
795
|
}
|
|
779
796
|
// Overwrite existing TrustedTypes policy.
|
|
797
|
+
const previousTrustedTypesPolicy = trustedTypesPolicy;
|
|
780
798
|
trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;
|
|
781
|
-
// Sign local variables required by `sanitize`.
|
|
782
|
-
|
|
799
|
+
// Sign local variables required by `sanitize`. If the supplied policy's
|
|
800
|
+
// `createHTML` is circular (i.e. it calls `DOMPurify.sanitize`), this
|
|
801
|
+
// throws via the re-entrancy guard. Restore the previous policy first so
|
|
802
|
+
// the instance is not left in a poisoned state. See #1422.
|
|
803
|
+
try {
|
|
804
|
+
emptyHTML = _createTrustedHTML('');
|
|
805
|
+
} catch (error) {
|
|
806
|
+
trustedTypesPolicy = previousTrustedTypesPolicy;
|
|
807
|
+
throw error;
|
|
808
|
+
}
|
|
783
809
|
} else {
|
|
784
810
|
// Uninitialized policy, attempt to initialize the internal dompurify policy.
|
|
785
|
-
if (trustedTypesPolicy === undefined) {
|
|
811
|
+
if (trustedTypesPolicy === undefined && cfg.TRUSTED_TYPES_POLICY !== null) {
|
|
786
812
|
trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);
|
|
787
813
|
}
|
|
788
814
|
// If creating the internal policy succeeded sign internal variables.
|
|
789
|
-
|
|
790
|
-
|
|
815
|
+
// Note: a falsy `trustedTypesPolicy` (null when policy creation failed or
|
|
816
|
+
// was skipped via `TRUSTED_TYPES_POLICY: null`, or undefined when no
|
|
817
|
+
// policy has been initialized yet) must be excluded here, otherwise we
|
|
818
|
+
// would call `.createHTML` on a non-policy and throw. See #1422.
|
|
819
|
+
if (trustedTypesPolicy && typeof emptyHTML === 'string') {
|
|
820
|
+
emptyHTML = _createTrustedHTML('');
|
|
791
821
|
}
|
|
792
822
|
}
|
|
823
|
+
/*
|
|
824
|
+
* Mirror the clone-before-mutate pattern already applied above for
|
|
825
|
+
* cfg.ADD_TAGS / cfg.ADD_ATTR: if any uponSanitize* hook is
|
|
826
|
+
* registered AND the set still points at the default constant,
|
|
827
|
+
* clone it. The hook then mutates the clone (in-call widening
|
|
828
|
+
* still works exactly as documented) and the next default-cfg
|
|
829
|
+
* call rebinds to the untouched original via the reassignment at
|
|
830
|
+
* the top of this function.
|
|
831
|
+
*/
|
|
832
|
+
if ((hooks.uponSanitizeElement.length > 0 || hooks.uponSanitizeAttribute.length > 0) && ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
|
|
833
|
+
ALLOWED_TAGS = clone(ALLOWED_TAGS);
|
|
834
|
+
}
|
|
835
|
+
if (hooks.uponSanitizeAttribute.length > 0 && ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
|
|
836
|
+
ALLOWED_ATTR = clone(ALLOWED_ATTR);
|
|
837
|
+
}
|
|
793
838
|
// Prevent further manipulation of configuration.
|
|
794
839
|
// Not available in IE8, Safari 5, etc.
|
|
795
840
|
if (freeze) {
|
|
@@ -949,7 +994,7 @@ function createDOMPurify() {
|
|
|
949
994
|
// Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)
|
|
950
995
|
dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
|
|
951
996
|
}
|
|
952
|
-
const dirtyPayload = trustedTypesPolicy ?
|
|
997
|
+
const dirtyPayload = trustedTypesPolicy ? _createTrustedHTML(dirty) : dirty;
|
|
953
998
|
/*
|
|
954
999
|
* Use the DOMParser API by default, fallback later if needs be
|
|
955
1000
|
* DOMParser not work for svg when has multiple root element.
|
|
@@ -1008,7 +1053,8 @@ function createDOMPurify() {
|
|
|
1008
1053
|
*
|
|
1009
1054
|
* @param node The root element whose character data should be scrubbed.
|
|
1010
1055
|
*/
|
|
1011
|
-
const
|
|
1056
|
+
const _scrubTemplateExpressions2 = function _scrubTemplateExpressions(node) {
|
|
1057
|
+
var _node$querySelectorAl, _node$querySelectorAl2;
|
|
1012
1058
|
node.normalize();
|
|
1013
1059
|
const walker = createNodeIterator.call(node.ownerDocument || node, node,
|
|
1014
1060
|
// eslint-disable-next-line no-bitwise
|
|
@@ -1022,6 +1068,15 @@ function createDOMPurify() {
|
|
|
1022
1068
|
currentNode.data = data;
|
|
1023
1069
|
currentNode = walker.nextNode();
|
|
1024
1070
|
}
|
|
1071
|
+
// NodeIterator does not descend into <template>.content per the DOM spec,
|
|
1072
|
+
// so we must explicitly recurse into each template's content fragment,
|
|
1073
|
+
// mirroring the approach used by _sanitizeShadowDOM.
|
|
1074
|
+
const templates = (_node$querySelectorAl = (_node$querySelectorAl2 = node.querySelectorAll) === null || _node$querySelectorAl2 === void 0 ? void 0 : _node$querySelectorAl2.call(node, 'template')) !== null && _node$querySelectorAl !== void 0 ? _node$querySelectorAl : [];
|
|
1075
|
+
arrayForEach(Array.from(templates), tmpl => {
|
|
1076
|
+
if (_isDocumentFragment(tmpl.content)) {
|
|
1077
|
+
_scrubTemplateExpressions2(tmpl.content);
|
|
1078
|
+
}
|
|
1079
|
+
});
|
|
1025
1080
|
};
|
|
1026
1081
|
/**
|
|
1027
1082
|
* _isClobbered
|
|
@@ -1032,32 +1087,6 @@ function createDOMPurify() {
|
|
|
1032
1087
|
* on direct reads. We use this check at the IN_PLACE entry-point and
|
|
1033
1088
|
* during attribute sanitization to refuse clobbered forms.
|
|
1034
1089
|
*
|
|
1035
|
-
* Realm safety (GHSA-hpcv-96wg-7vj8): every check in this function must
|
|
1036
|
-
* work for foreign-realm forms — e.g. a <form> created inside a same-
|
|
1037
|
-
* origin iframe and then handed to a parent-realm DOMPurify instance
|
|
1038
|
-
* with IN_PLACE: true. The original implementation used
|
|
1039
|
-
* `element instanceof HTMLFormElement` and `element.attributes
|
|
1040
|
-
* instanceof NamedNodeMap`, both of which are realm-bound: a foreign-
|
|
1041
|
-
* realm form is an instance of the *foreign* realm's HTMLFormElement,
|
|
1042
|
-
* not the parent realm's. The instanceof short-circuited to false and
|
|
1043
|
-
* the function returned false (= not clobbered) regardless of how
|
|
1044
|
-
* thoroughly the form was clobbered. Sanitize then walked a clobbered
|
|
1045
|
-
* .attributes and missed every attribute on the form root, leaving
|
|
1046
|
-
* onmouseover / onclick / formaction / etc. intact.
|
|
1047
|
-
*
|
|
1048
|
-
* The realm-independent replacements:
|
|
1049
|
-
* - HTMLFormElement detection — read the tag name through the cached
|
|
1050
|
-
* Node.prototype.nodeName getter. WebIDL getters operate on internal
|
|
1051
|
-
* slots that exist on every real Node regardless of which realm
|
|
1052
|
-
* minted the JS wrapper, so getNodeName(foreignForm) === "FORM".
|
|
1053
|
-
* - NamedNodeMap detection — compare the direct .attributes read
|
|
1054
|
-
* against the cached Element.prototype.attributes getter. Same
|
|
1055
|
-
* equality-probe pattern we use for .childNodes: if a clobbering
|
|
1056
|
-
* child shadows the named property, the two reads diverge; if not,
|
|
1057
|
-
* both return the same NamedNodeMap (same-realm OR foreign-realm —
|
|
1058
|
-
* doesn't matter, both are the canonical attributes object for the
|
|
1059
|
-
* node).
|
|
1060
|
-
*
|
|
1061
1090
|
* @param element element to check for clobbering attacks
|
|
1062
1091
|
* @return true if clobbered, false if safe
|
|
1063
1092
|
*/
|
|
@@ -1079,6 +1108,14 @@ function createDOMPurify() {
|
|
|
1079
1108
|
// (same-realm OR foreign-realm) has both reads pointing at the same
|
|
1080
1109
|
// canonical NamedNodeMap.
|
|
1081
1110
|
element.attributes !== getAttributes(element) || typeof element.removeAttribute !== 'function' || typeof element.setAttribute !== 'function' || typeof element.namespaceURI !== 'string' || typeof element.insertBefore !== 'function' || typeof element.hasChildNodes !== 'function' ||
|
|
1111
|
+
// NodeType clobbering probe. Cached Node.prototype.nodeType getter
|
|
1112
|
+
// returns the integer 1 for any Element regardless of realm; direct
|
|
1113
|
+
// read on a clobbered form (e.g. <input name="nodeType">) returns
|
|
1114
|
+
// the named child element. Cheap addition — nodeType is read from
|
|
1115
|
+
// an internal slot, no serialization cost — and removes a residual
|
|
1116
|
+
// clobbering surface used by several mXSS / PI / comment branches
|
|
1117
|
+
// in _sanitizeElements that compare currentNode.nodeType directly.
|
|
1118
|
+
element.nodeType !== getNodeType(element) ||
|
|
1082
1119
|
// HTMLFormElement has [LegacyOverrideBuiltIns]: a descendant named
|
|
1083
1120
|
// "childNodes" shadows the prototype getter. Direct reads of
|
|
1084
1121
|
// form.childNodes from a clobbered form return the named child
|
|
@@ -1095,14 +1132,6 @@ function createDOMPurify() {
|
|
|
1095
1132
|
/**
|
|
1096
1133
|
* Checks whether the given value is a DocumentFragment from any realm.
|
|
1097
1134
|
*
|
|
1098
|
-
* Realm safety (GHSA-hpcv-96wg-7vj8): the original sites used
|
|
1099
|
-
* `value instanceof DocumentFragment`, which is realm-bound — a fragment
|
|
1100
|
-
* from a foreign realm (template content or shadow root from an iframe
|
|
1101
|
-
* document) is an instance of the foreign realm's DocumentFragment, not
|
|
1102
|
-
* the parent realm's, so the check returned false and the template-
|
|
1103
|
-
* content / shadow-root recursion was silently skipped. The attacker
|
|
1104
|
-
* payload inside survived untouched.
|
|
1105
|
-
*
|
|
1106
1135
|
* The realm-independent replacement reads `nodeType` through the cached
|
|
1107
1136
|
* Node.prototype getter and compares to the DOCUMENT_FRAGMENT_NODE
|
|
1108
1137
|
* constant (11). nodeType is a numeric value resolved from the node's
|
|
@@ -1129,12 +1158,6 @@ function createDOMPurify() {
|
|
|
1129
1158
|
* sanitize() to silently stringify them and reset IN_PLACE to false,
|
|
1130
1159
|
* returning the original node unsanitized. See GHSA-4w3q-35jp-p934.
|
|
1131
1160
|
*
|
|
1132
|
-
* Implementation: call the cached `nodeType` getter from Node.prototype
|
|
1133
|
-
* directly on the value. This bypasses any clobbered instance property
|
|
1134
|
-
* (e.g. a child element named "nodeType") and works across realms
|
|
1135
|
-
* because the WebIDL `nodeType` getter reads an internal slot that
|
|
1136
|
-
* every real Node has, regardless of which window minted it.
|
|
1137
|
-
*
|
|
1138
1161
|
* @param value object to check whether it's a DOM node
|
|
1139
1162
|
* @return true if value is a DOM node from any realm
|
|
1140
1163
|
*/
|
|
@@ -1172,7 +1195,7 @@ function createDOMPurify() {
|
|
|
1172
1195
|
return true;
|
|
1173
1196
|
}
|
|
1174
1197
|
/* Now let's check the element's type and name */
|
|
1175
|
-
const tagName = transformCaseFunc(currentNode.nodeName);
|
|
1198
|
+
const tagName = transformCaseFunc(getNodeName ? getNodeName(currentNode) : currentNode.nodeName);
|
|
1176
1199
|
/* Execute a hook if present */
|
|
1177
1200
|
_executeHooks(hooks.uponSanitizeElement, currentNode, {
|
|
1178
1201
|
tagName,
|
|
@@ -1209,10 +1232,17 @@ function createDOMPurify() {
|
|
|
1209
1232
|
return false;
|
|
1210
1233
|
}
|
|
1211
1234
|
}
|
|
1212
|
-
/* Keep content except for bad-listed elements
|
|
1235
|
+
/* Keep content except for bad-listed elements.
|
|
1236
|
+
Use the cached prototype getters exclusively — the previous code
|
|
1237
|
+
had `|| currentNode.parentNode` / `|| currentNode.childNodes`
|
|
1238
|
+
fallbacks, but the cached getters always return the canonical
|
|
1239
|
+
value (or null for a real parent-less node), so the fallback
|
|
1240
|
+
path was dead in safe cases and a clobbering surface in unsafe
|
|
1241
|
+
ones. Falsy cached results stay falsy; the `if (childNodes &&
|
|
1242
|
+
parentNode)` check already gates correctly. */
|
|
1213
1243
|
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
|
|
1214
|
-
const parentNode = getParentNode(currentNode)
|
|
1215
|
-
const childNodes = getChildNodes(currentNode)
|
|
1244
|
+
const parentNode = getParentNode(currentNode);
|
|
1245
|
+
const childNodes = getChildNodes(currentNode);
|
|
1216
1246
|
if (childNodes && parentNode) {
|
|
1217
1247
|
const childCount = childNodes.length;
|
|
1218
1248
|
for (let i = childCount - 1; i >= 0; --i) {
|
|
@@ -1408,7 +1438,7 @@ function createDOMPurify() {
|
|
|
1408
1438
|
switch (trustedTypes.getAttributeType(lcTag, lcName)) {
|
|
1409
1439
|
case 'TrustedHTML':
|
|
1410
1440
|
{
|
|
1411
|
-
value =
|
|
1441
|
+
value = _createTrustedHTML(value);
|
|
1412
1442
|
break;
|
|
1413
1443
|
}
|
|
1414
1444
|
case 'TrustedScriptURL':
|
|
@@ -1465,6 +1495,24 @@ function createDOMPurify() {
|
|
|
1465
1495
|
if (_isDocumentFragment(shadowNode.content)) {
|
|
1466
1496
|
_sanitizeShadowDOM2(shadowNode.content);
|
|
1467
1497
|
}
|
|
1498
|
+
/* An element iterated here may itself host an attached
|
|
1499
|
+
shadow root. The default NodeIterator does not enter shadow
|
|
1500
|
+
trees, so a shadow root nested inside template.content was
|
|
1501
|
+
previously reached by no walk at all (the pre-pass at
|
|
1502
|
+
_sanitizeAttachedShadowRoots descends via childNodes, which
|
|
1503
|
+
doesn't enter template.content; the template-content recursion
|
|
1504
|
+
above iterates the content but never inspected shadowRoot).
|
|
1505
|
+
Walk it explicitly. The nodeType guard avoids reading
|
|
1506
|
+
shadowRoot off text / comment / CDATA / PI nodes that the
|
|
1507
|
+
iterator also surfaces. */
|
|
1508
|
+
const shadowNodeType = getNodeType ? getNodeType(shadowNode) : shadowNode.nodeType;
|
|
1509
|
+
if (shadowNodeType === NODE_TYPE.element) {
|
|
1510
|
+
const innerSr = getShadowRoot ? getShadowRoot(shadowNode) : shadowNode.shadowRoot;
|
|
1511
|
+
if (_isDocumentFragment(innerSr)) {
|
|
1512
|
+
_sanitizeAttachedShadowRoots2(innerSr);
|
|
1513
|
+
_sanitizeShadowDOM2(innerSr);
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1468
1516
|
}
|
|
1469
1517
|
/* Execute a hook if present */
|
|
1470
1518
|
_executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);
|
|
@@ -1486,17 +1534,6 @@ function createDOMPurify() {
|
|
|
1486
1534
|
* existing _sanitizeShadowDOM template-content recursion) stay
|
|
1487
1535
|
* untouched — string-input paths are not affected.
|
|
1488
1536
|
*
|
|
1489
|
-
* DOM-Clobbering hardening: HTMLFormElement carries the WebIDL
|
|
1490
|
-
* [LegacyOverrideBuiltIns] extended attribute, so a descendant element
|
|
1491
|
-
* named `nodeType`, `shadowRoot`, or `childNodes` shadows the matching
|
|
1492
|
-
* prototype getter on the form. Reading those properties directly off
|
|
1493
|
-
* the node would let an attacker steer this walk past shadow hosts
|
|
1494
|
-
* (e.g. <input name="childNodes"> collapses the form's child list to
|
|
1495
|
-
* the input itself, so descent stops dead and any shadow root deeper
|
|
1496
|
-
* in the subtree is never sanitized). Every property access here is
|
|
1497
|
-
* therefore routed through the cached prototype getter; the form's
|
|
1498
|
-
* named-property getter cannot intercept those reads.
|
|
1499
|
-
*
|
|
1500
1537
|
* @param root the subtree root to walk for attached shadow roots
|
|
1501
1538
|
*/
|
|
1502
1539
|
const _sanitizeAttachedShadowRoots2 = function _sanitizeAttachedShadowRoots(root) {
|
|
@@ -1532,6 +1569,16 @@ function createDOMPurify() {
|
|
|
1532
1569
|
for (const child of snapshot) {
|
|
1533
1570
|
_sanitizeAttachedShadowRoots2(child);
|
|
1534
1571
|
}
|
|
1572
|
+
/* When the root is a <template>, also descend into root.content */
|
|
1573
|
+
if (nodeType === NODE_TYPE.element) {
|
|
1574
|
+
const rootName = getNodeName ? getNodeName(root) : null;
|
|
1575
|
+
if (typeof rootName === 'string' && transformCaseFunc(rootName) === 'template') {
|
|
1576
|
+
const content = root.content;
|
|
1577
|
+
if (_isDocumentFragment(content)) {
|
|
1578
|
+
_sanitizeAttachedShadowRoots2(content);
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1535
1582
|
};
|
|
1536
1583
|
// eslint-disable-next-line complexity
|
|
1537
1584
|
DOMPurify.sanitize = function (dirty) {
|
|
@@ -1622,7 +1669,7 @@ function createDOMPurify() {
|
|
|
1622
1669
|
if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&
|
|
1623
1670
|
// eslint-disable-next-line unicorn/prefer-includes
|
|
1624
1671
|
dirty.indexOf('<') === -1) {
|
|
1625
|
-
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ?
|
|
1672
|
+
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(dirty) : dirty;
|
|
1626
1673
|
}
|
|
1627
1674
|
/* Initialize the document to work on */
|
|
1628
1675
|
body = _initDocument(dirty);
|
|
@@ -1654,14 +1701,14 @@ function createDOMPurify() {
|
|
|
1654
1701
|
/* If we sanitized `dirty` in-place, return it. */
|
|
1655
1702
|
if (IN_PLACE) {
|
|
1656
1703
|
if (SAFE_FOR_TEMPLATES) {
|
|
1657
|
-
|
|
1704
|
+
_scrubTemplateExpressions2(dirty);
|
|
1658
1705
|
}
|
|
1659
1706
|
return dirty;
|
|
1660
1707
|
}
|
|
1661
1708
|
/* Return sanitized string or DOM */
|
|
1662
1709
|
if (RETURN_DOM) {
|
|
1663
1710
|
if (SAFE_FOR_TEMPLATES) {
|
|
1664
|
-
|
|
1711
|
+
_scrubTemplateExpressions2(body);
|
|
1665
1712
|
}
|
|
1666
1713
|
if (RETURN_DOM_FRAGMENT) {
|
|
1667
1714
|
returnNode = createDocumentFragment.call(body.ownerDocument);
|
|
@@ -1695,7 +1742,7 @@ function createDOMPurify() {
|
|
|
1695
1742
|
serializedHTML = stringReplace(serializedHTML, expr, ' ');
|
|
1696
1743
|
});
|
|
1697
1744
|
}
|
|
1698
|
-
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ?
|
|
1745
|
+
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(serializedHTML) : serializedHTML;
|
|
1699
1746
|
};
|
|
1700
1747
|
DOMPurify.setConfig = function () {
|
|
1701
1748
|
let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|