Skip to content

Commit 6158ecb

Browse files
authored
Merge pull request #1103 from cure53/main
Getting 3.x branch ready for 3.2.6 release
2 parents 7806004 + 848463b commit 6158ecb

File tree

14 files changed

+144
-166
lines changed

14 files changed

+144
-166
lines changed

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ DOMPurify is written in JavaScript and works in all modern browsers (Safari (10+
1010

1111
**Note that [DOMPurify v2.5.8](https://github.com/cure53/DOMPurify/releases/tag/2.5.8) is the latest version supporting MSIE. For important security updates compatible with MSIE, please use the [2.x branch](https://github.com/cure53/DOMPurify/tree/2.x).**
1212

13-
Our automated tests cover [28 different browsers](https://github.com/cure53/DOMPurify/blob/main/test/karma.custom-launchers.config.js#L5) right now, more to come. We also cover Node.js v18.x, v19.x, v20.x, v21.x, v12.x and v23.x, running DOMPurify on [jsdom](https://github.com/jsdom/jsdom). Older Node versions are known to work as well, but hey... no guarantees.
13+
Our automated tests cover [28 different browsers](https://github.com/cure53/DOMPurify/blob/main/test/karma.custom-launchers.config.js#L5) right now, more to come. We also cover Node.js v18.x, v19.x, v20.x, v21.x, v22.x and v23.x, running DOMPurify on [jsdom](https://github.com/jsdom/jsdom). Older Node versions are known to work as well, but hey... no guarantees.
1414

1515
DOMPurify is written by security people who have vast background in web attacks and XSS. Fear not. For more details please also read about our [Security Goals & Threat Model](https://github.com/cure53/DOMPurify/wiki/Security-Goals-&-Threat-Model). Please, read it. Like, really.
1616

@@ -22,10 +22,10 @@ DOMPurify sanitizes HTML and prevents XSS attacks. You can feed DOMPurify with s
2222

2323
It's easy. Just include DOMPurify on your website.
2424

25-
### Using the unminified development version
25+
### Using the unminified version (source-map available)
2626

2727
```html
28-
<script type="text/javascript" src="src/purify.js"></script>
28+
<script type="text/javascript" src="dist/purify.js"></script>
2929
```
3030

3131
### Using the minified and tested production version (source-map available)
@@ -303,7 +303,7 @@ const clean = DOMPurify.sanitize(dirty, {
303303
TRUSTED_TYPES_POLICY: trustedTypes.createPolicy({
304304
createHTML(s) { return s},
305305
createScriptURL(s) { return s},
306-
}
306+
})
307307
});
308308
```
309309
### Influence how we sanitize
@@ -385,7 +385,7 @@ DOMPurify.addHook(
385385

386386
We are currently using Github Actions in combination with BrowserStack. This gives us the possibility to confirm for each and every commit that all is going according to plan in all supported browsers. Check out the build logs here: https://github.com/cure53/DOMPurify/actions
387387

388-
You can further run local tests by executing `npm test`. The tests work fine with Node.js v0.6.2 and jsdom@8.5.0.
388+
You can further run local tests by executing `npm run test`.
389389

390390
All relevant commits will be signed with the key `0x24BB6BF4` for additional security (since 8th of April 2016).
391391

dist/purify.cjs.js

Lines changed: 24 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/purify.cjs.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/purify.es.mjs

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ const ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
202202
const TMPLIT_EXPR = seal(/\$\{[\w\W]*/gm); // eslint-disable-line unicorn/better-regex
203203
const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); // eslint-disable-line no-useless-escape
204204
const ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
205-
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
205+
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
206206
);
207207
const IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
208208
const ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex
@@ -538,8 +538,8 @@ function createDOMPurify() {
538538
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;
539539
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;
540540
FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
541-
FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : {};
542-
FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : {};
541+
FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone({});
542+
FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});
543543
USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES : false;
544544
ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
545545
ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
@@ -904,7 +904,7 @@ function createDOMPurify() {
904904
allowedTags: ALLOWED_TAGS
905905
});
906906
/* Detect mXSS attempts abusing namespace confusion */
907-
if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\w!]/g, currentNode.innerHTML) && regExpTest(/<[/\w!]/g, currentNode.textContent)) {
907+
if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\w!]/g, currentNode.innerHTML) && regExpTest(/<[/\w!]/g, currentNode.textContent)) {
908908
_forceRemove(currentNode);
909909
return true;
910910
}
@@ -1056,7 +1056,8 @@ function createDOMPurify() {
10561056
value: attrValue
10571057
} = attr;
10581058
const lcName = transformCaseFunc(name);
1059-
let value = name === 'value' ? attrValue : stringTrim(attrValue);
1059+
const initValue = attrValue;
1060+
let value = name === 'value' ? initValue : stringTrim(initValue);
10601061
/* Execute a hook if present */
10611062
hookEvent.attrName = lcName;
10621063
hookEvent.attrValue = value;
@@ -1082,10 +1083,9 @@ function createDOMPurify() {
10821083
if (hookEvent.forceKeepAttr) {
10831084
continue;
10841085
}
1085-
/* Remove attribute */
1086-
_removeAttribute(name, currentNode);
10871086
/* Did the hooks approve of the attribute? */
10881087
if (!hookEvent.keepAttr) {
1088+
_removeAttribute(name, currentNode);
10891089
continue;
10901090
}
10911091
/* Work around a security issue in jQuery 3.0 */
@@ -1102,6 +1102,7 @@ function createDOMPurify() {
11021102
/* Is `value` valid for this attribute? */
11031103
const lcTag = transformCaseFunc(currentNode.nodeName);
11041104
if (!_isValidAttribute(lcTag, lcName, value)) {
1105+
_removeAttribute(name, currentNode);
11051106
continue;
11061107
}
11071108
/* Handle attributes that require Trusted Types */
@@ -1122,19 +1123,23 @@ function createDOMPurify() {
11221123
}
11231124
}
11241125
/* Handle invalid data-* attribute set by try-catching it */
1125-
try {
1126-
if (namespaceURI) {
1127-
currentNode.setAttributeNS(namespaceURI, name, value);
1128-
} else {
1129-
/* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
1130-
currentNode.setAttribute(name, value);
1131-
}
1132-
if (_isClobbered(currentNode)) {
1133-
_forceRemove(currentNode);
1134-
} else {
1135-
arrayPop(DOMPurify.removed);
1126+
if (value !== initValue) {
1127+
try {
1128+
if (namespaceURI) {
1129+
currentNode.setAttributeNS(namespaceURI, name, value);
1130+
} else {
1131+
/* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
1132+
currentNode.setAttribute(name, value);
1133+
}
1134+
if (_isClobbered(currentNode)) {
1135+
_forceRemove(currentNode);
1136+
} else {
1137+
arrayPop(DOMPurify.removed);
1138+
}
1139+
} catch (_) {
1140+
_removeAttribute(name, currentNode);
11361141
}
1137-
} catch (_) {}
1142+
}
11381143
}
11391144
/* Execute a hook if present */
11401145
_executeHooks(hooks.afterSanitizeAttributes, currentNode, null);

dist/purify.es.mjs.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/purify.js

Lines changed: 24 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/purify.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/purify.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/purify.min.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/server.js

Lines changed: 0 additions & 42 deletions
This file was deleted.

0 commit comments

Comments
 (0)