Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
4cd2f44
Update README.md
cure53 Dec 8, 2025
472f52a
build(deps): bump qs and body-parser (#1178)
dependabot[bot] Jan 3, 2026
5b69ff6
chore: update tested nodejs version (#1181)
Rotzbua Jan 7, 2026
50f6dfe
chore: update dependencies (#1183)
Rotzbua Jan 9, 2026
934a698
Revert "chore: update dependencies (#1183)" (#1184)
cure53 Jan 9, 2026
5d3bed8
fix: remove deprecated call `QUnit.load()` (#1188)
Rotzbua Jan 13, 2026
7919ade
fix: prettier windows end of line not lf (#1186)
Rotzbua Jan 13, 2026
eb5cf80
remove abandoned dependency `npm-run-all` (#1190)
Rotzbua Jan 22, 2026
431f93f
remove dependency `lodash.sample` (#1191)
Rotzbua Jan 22, 2026
843d64f
build(deps-dev): bump lodash-es from 4.17.21 to 4.17.23 (#1192)
dependabot[bot] Jan 22, 2026
55970a9
build(deps): bump lodash from 4.17.21 to 4.17.23 (#1193)
dependabot[bot] Jan 22, 2026
874c71f
Update README.md (#1195)
cure53 Feb 13, 2026
aa3d83e
build(deps-dev): bump webpack from 5.94.0 to 5.105.0 (#1194)
dependabot[bot] Feb 13, 2026
1785cb4
Update README.md
cure53 Feb 13, 2026
43ea6f4
Update README.md
cure53 Feb 13, 2026
28a29db
build(deps): bump qs from 6.14.1 to 6.14.2 (#1196)
dependabot[bot] Feb 13, 2026
c361baa
fix: Added smaller fixes addressing several LLM bug reports
cure53 Feb 24, 2026
729097f
fix: Adding a slighjtly tighter regex because of possible jsdom woes
cure53 Mar 3, 2026
d13346f
build(deps-dev): bump minimatch from 3.1.2 to 3.1.5 (#1200)
dependabot[bot] Mar 3, 2026
53e4f5b
build(deps-dev): bump rollup from 3.29.5 to 3.30.0 (#1199)
dependabot[bot] Mar 3, 2026
c861f5a
fix: Adding a slightly tighter regex because of possible jsdom woes
cure53 Mar 3, 2026
cd85175
Merge branch 'main' of github.com:cure53/DOMPurify
cure53 Mar 3, 2026
302b51d
fix: Expanded the regex ever so slightly to also cover script
cure53 Mar 3, 2026
6202c7e
build(deps): bump @tootallnate/once and jsdom (#1204)
dependabot[bot] Mar 5, 2026
2726c74
chore: Preparing 3.3.2 release
cure53 Mar 5, 2026
988b888
fix: moved back from jsdom 28 to jsdom 20
cure53 Mar 5, 2026
c3efd48
fix: moved back from jsdom 28 to jsdom 20
cure53 Mar 5, 2026
d5ff1a8
Merge branch 'main' of github.com:cure53/DOMPurify
cure53 Mar 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text eol=lf
4 changes: 2 additions & 2 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:

strategy:
matrix:
node-version: [18.x, 19.x, 20.x, 21.x, 22.x, 23.x]
node-version: [20.x, 22.x, 24.x, 25.x]

steps:
- name: Checkout
Expand All @@ -39,7 +39,7 @@ jobs:
with:
run: npm run test:ci
env:
TEST_BROWSERSTACK: ${{ startsWith(matrix.node-version, '22') }}
TEST_BROWSERSTACK: ${{ startsWith(matrix.node-version, '24') }}
TEST_PROBE_ONLY: ${{ github.ref != 'refs/heads/main' && github.ref != 'refs/heads/2.x' }}
BS_USERNAME: ${{ secrets.BS_USERNAME }}
BS_ACCESSKEY: ${{ secrets.BS_ACCESSKEY }}
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# DOMPurify

[![npm](https://badge.fury.io/js/dompurify.svg)](http://badge.fury.io/js/dompurify) ![Tests](https://github.com/cure53/DOMPurify/workflows/Build%20and%20Test/badge.svg) [![Downloads](https://img.shields.io/npm/dm/dompurify.svg)](https://www.npmjs.com/package/dompurify) ![npm package minimized gzipped size (select exports)](https://img.shields.io/bundlejs/size/dompurify?color=%233C1&label=gzipped) [![dependents](https://badgen.net/github/dependents-repo/cure53/dompurify?color=green&label=dependents)](https://github.com/cure53/DOMPurify/network/dependents) [![Build Status](https://app.cloudback.it/badge/cure53/DOMPurify)](https://cloudback.it)
[![npm](https://badge.fury.io/js/dompurify.svg)](http://badge.fury.io/js/dompurify) ![Tests](https://github.com/cure53/DOMPurify/workflows/Build%20and%20Test/badge.svg) [![Downloads](https://img.shields.io/npm/dm/dompurify.svg)](https://www.npmjs.com/package/dompurify) ![npm package minimized gzipped size (select exports)](https://img.shields.io/bundlejs/size/dompurify?color=%233C1&label=gzip) [![dependents](https://badgen.net/github/dependents-repo/cure53/dompurify?color=green&label=dependents)](https://github.com/cure53/DOMPurify/network/dependents) [![Cloudback](https://app.cloudback.it/badge/cure53/DOMPurify)](https://cloudback.it)

DOMPurify is a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG.

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 **v3.3.1**.
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 **v3.3.2**.

DOMPurify is written in JavaScript and works in all modern browsers (Safari (10+), Opera (15+), Edge, Firefox and Chrome - as well as almost anything else using Blink, Gecko or WebKit). It doesn't break on MSIE or other legacy browsers. It simply does nothing.
DOMPurify runs as JavaScript and works in all modern browsers (Safari (10+), Opera (15+), Edge, Firefox and Chrome - as well as almost anything else using Blink, Gecko or WebKit). It doesn't break on MSIE or other legacy browsers. It simply does nothing.

**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).**

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.
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 v20.x, v22.x, 24.x and v25.x, running DOMPurify on [jsdom](https://github.com/jsdom/jsdom). Older Node versions are known to work as well, but hey... no guarantees.

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.

Expand Down Expand Up @@ -65,7 +65,7 @@ After sanitizing your markup, you can also have a look at the property `DOMPurif

### Running DOMPurify on the server

DOMPurify technically also works server-side with Node.js. Our support strives to follow the [Node.js release cycle](https://nodejs.org/en/about/releases/).
DOMPurify technically also works server-side with Node.js. Our support strives to follow the [Node.js release cycle](https://nodejs.org/en/about/previous-releases).

Running DOMPurify on the server requires a DOM to be present, which is probably no surprise. Usually, [jsdom](https://github.com/jsdom/jsdom) is the tool of choice and we **strongly recommend** to use the latest version of _jsdom_.

Expand Down Expand Up @@ -440,7 +440,7 @@ We support `npm` officially. GitHub Actions workflow is configured to install de

#### Scripts

We rely on npm run-scripts for integrating with our tooling infrastructure. We use ESLint as a pre-commit hook to ensure code consistency. Moreover, to ease formatting we use [prettier](https://github.com/prettier/prettier) while building the `/dist` assets happens through `rollup`.
We use ESLint as a pre-commit hook to ensure code consistency. Moreover, to ease formatting we use [prettier](https://github.com/prettier/prettier) while building the `/dist` assets happens through `rollup`.

These are our npm scripts:

Expand Down
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dompurify",
"version": "3.3.1",
"version": "3.3.2",
"homepage": "https://github.com/cure53/DOMPurify",
"author": "Cure53 <info@cure53.de>",
"description": "A DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG",
Expand Down
2 changes: 1 addition & 1 deletion dist/purify.cjs.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*! @license DOMPurify 3.3.1 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.3.1/LICENSE */
/*! @license DOMPurify 3.3.2 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.3.2/LICENSE */

import { TrustedTypePolicy, TrustedHTML, TrustedTypesWindow } from 'trusted-types/lib/index.js';

Expand Down
19 changes: 15 additions & 4 deletions dist/purify.cjs.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/purify.cjs.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/purify.es.d.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*! @license DOMPurify 3.3.1 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.3.1/LICENSE */
/*! @license DOMPurify 3.3.2 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.3.2/LICENSE */

import { TrustedTypePolicy, TrustedHTML, TrustedTypesWindow } from 'trusted-types/lib/index.js';

Expand Down
19 changes: 15 additions & 4 deletions dist/purify.es.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*! @license DOMPurify 3.3.1 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.3.1/LICENSE */
/*! @license DOMPurify 3.3.2 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.3.2/LICENSE */

const {
entries,
Expand Down Expand Up @@ -305,7 +305,7 @@ const _createHooksMap = function _createHooksMap() {
function createDOMPurify() {
let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
const DOMPurify = root => createDOMPurify(root);
DOMPurify.version = '3.3.1';
DOMPurify.version = '3.3.2';
DOMPurify.removed = [];
if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
// Not running in a browser, provide a factory function
Expand Down Expand Up @@ -600,7 +600,7 @@ function createDOMPurify() {
/* Parse profile info */
if (USE_PROFILES) {
ALLOWED_TAGS = addToSet({}, text);
ALLOWED_ATTR = [];
ALLOWED_ATTR = create(null);
if (USE_PROFILES.html === true) {
addToSet(ALLOWED_TAGS, html$1);
addToSet(ALLOWED_ATTR, html);
Expand All @@ -621,6 +621,13 @@ function createDOMPurify() {
addToSet(ALLOWED_ATTR, xml);
}
}
/* Prevent function-based ADD_ATTR / ADD_TAGS from leaking across calls */
if (!objectHasOwnProperty(cfg, 'ADD_TAGS')) {
EXTRA_ELEMENT_HANDLING.tagCheck = null;
}
if (!objectHasOwnProperty(cfg, 'ADD_ATTR')) {
EXTRA_ELEMENT_HANDLING.attributeCheck = null;
}
/* Merge configuration parameters */
if (cfg.ADD_TAGS) {
if (typeof cfg.ADD_TAGS === 'function') {
Expand Down Expand Up @@ -1018,6 +1025,10 @@ function createDOMPurify() {
*/
// eslint-disable-next-line complexity
const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
/* FORBID_ATTR must always win, even if ADD_ATTR predicate would allow it */
if (FORBID_ATTR[lcName]) {
return false;
}
/* Make sure attribute cannot clobber */
if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
return false;
Expand Down Expand Up @@ -1110,7 +1121,7 @@ function createDOMPurify() {
value = SANITIZE_NAMED_PROPS_PREFIX + value;
}
/* Work around a security issue with comments inside attributes */
if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|title|textarea)/i, value)) {
if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) {
_removeAttribute(name, currentNode);
continue;
}
Expand Down
2 changes: 1 addition & 1 deletion dist/purify.es.mjs.map

Large diffs are not rendered by default.

19 changes: 15 additions & 4 deletions dist/purify.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/purify.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/purify.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/purify.min.js.map

Large diffs are not rendered by default.

Loading
Loading