Skip to content

Commit 699b1c9

Browse files
authoredFeb 20, 2024··
Merge pull request #913 from cure53/main
Getting 3.x branch ready for 3.0.9 release
2 parents ec1346a + 7bc954c commit 699b1c9

32 files changed

+525
-729
lines changed
 

‎README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

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

9-
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.0.8**.
9+
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.0.9**.
1010

1111
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.
1212

@@ -413,6 +413,6 @@ Many people helped and help DOMPurify become what it is and need to be acknowled
413413
414414
## Testing powered by
415415
416-
<a target="_blank" href="https://www.browserstack.com/"><img width="200" src="https://www.browserstack.com/images/layout/browserstack-logo-600x315.png"></a><br>
416+
<a target="_blank" href="https://www.browserstack.com/"><img width="200" src="https://github.com/cure53/DOMPurify/assets/6709482/f70be7eb-8fc4-41ea-9653-9d359235328f"></a><br>
417417
418418
And last but not least, thanks to [BrowserStack Open-Source Program](https://www.browserstack.com/open-source) for supporting this project with their services for free and delivering excellent, dedicated and very professional support on top of that.

‎bower.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "DOMPurify",
3-
"version": "3.0.8",
3+
"version": "3.0.9",
44
"homepage": "https://github.com/cure53/DOMPurify",
55
"author": "Cure53 <info@cure53.de>",
66
"description": "A DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG",

‎demos/README.md

+40-40
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ This is the relevant code:
1212

1313
```javascript
1414
// Clean HTML string and write into our DIV
15-
var clean = DOMPurify.sanitize(dirty);
15+
const clean = DOMPurify.sanitize(dirty);
1616
```
1717

1818
### Config Demo [Link](config-demo.html)
@@ -24,10 +24,10 @@ This is the relevant code:
2424
```javascript
2525
// Specify a configuration directive, only <P> elements allowed
2626
// Note: We want to also keep <p>'s text content, so we add #text too
27-
var config = { ALLOWED_TAGS: ['p', '#text'], KEEP_CONTENT: false };
27+
const config = { ALLOWED_TAGS: ['p', '#text'], KEEP_CONTENT: false };
2828

2929
// Clean HTML string and write into our DIV
30-
var clean = DOMPurify.sanitize(dirty, config);
30+
const clean = DOMPurify.sanitize(dirty, config);
3131
```
3232

3333
### Advanced Config Demo [Link](advanced-config-demo.html)
@@ -38,7 +38,7 @@ This is the relevant code:
3838

3939
```javascript
4040
// Specify a configuration directive
41-
var config = {
41+
const config = {
4242
ALLOWED_TAGS: ['p', '#text'], // only <P> and text nodes
4343
KEEP_CONTENT: false, // remove content from non-allow-listed nodes too
4444
ADD_ATTR: ['kitty-litter'], // permit kitty-litter attributes
@@ -47,7 +47,7 @@ var config = {
4747
};
4848

4949
// Clean HTML string and write into our DIV
50-
var clean = DOMPurify.sanitize(dirty, config);
50+
const clean = DOMPurify.sanitize(dirty, config);
5151
```
5252

5353
### Hooks Demo [Link](hooks-demo.html)
@@ -66,7 +66,7 @@ DOMPurify.addHook('beforeSanitizeAttributes', function (node) {
6666
});
6767

6868
// Clean HTML string and write into our DIV
69-
var clean = DOMPurify.sanitize(dirty);
69+
const clean = DOMPurify.sanitize(dirty);
7070
```
7171

7272
### Add hooks and remove hooks [Link](hooks-removal-demo.html)
@@ -85,13 +85,13 @@ DOMPurify.addHook('beforeSanitizeAttributes', function (node) {
8585
});
8686

8787
// Clean HTML string and write into our DIV
88-
var clean = DOMPurify.sanitize(dirty);
88+
let clean = DOMPurify.sanitize(dirty);
8989

9090
// now let's remove the hook again
9191
console.log(DOMPurify.removeHook('beforeSanitizeAttributes'));
9292

9393
// Clean HTML string and write into our DIV
94-
var clean = DOMPurify.sanitize(dirty);
94+
let clean = DOMPurify.sanitize(dirty);
9595
```
9696

9797
### Hook to open all links in a new window [Link](hooks-target-blank-demo.html)
@@ -117,7 +117,7 @@ DOMPurify.addHook('afterSanitizeAttributes', function (node) {
117117
});
118118

119119
// Clean HTML string and write into our DIV
120-
var clean = DOMPurify.sanitize(dirty);
120+
const clean = DOMPurify.sanitize(dirty);
121121
```
122122

123123
### Hook to white-list safe URI Schemes [Link](hooks-scheme-allowlist.html)
@@ -130,15 +130,15 @@ This is the relevant code:
130130

131131
```javascript
132132
// allowed URI schemes
133-
var allowlist = ['http', 'https', 'ftp'];
133+
const allowlist = ['http', 'https', 'ftp'];
134134

135135
// build fitting regex
136-
var regex = RegExp('^(' + allowlist.join('|') + '):', 'gim');
136+
const regex = RegExp('^(' + allowlist.join('|') + '):', 'gim');
137137

138138
// Add a hook to enforce URI scheme allow-list
139139
DOMPurify.addHook('afterSanitizeAttributes', function (node) {
140140
// build an anchor to map URLs to
141-
var anchor = document.createElement('a');
141+
const anchor = document.createElement('a');
142142

143143
// check all href attributes for validity
144144
if (node.hasAttribute('href')) {
@@ -164,7 +164,7 @@ DOMPurify.addHook('afterSanitizeAttributes', function (node) {
164164
});
165165

166166
// Clean HTML string and write into our DIV
167-
var clean = DOMPurify.sanitize(dirty);
167+
const clean = DOMPurify.sanitize(dirty);
168168
```
169169

170170
### Hook to allow and sand-box all JavaScript [Link](hooks-mentaljs-demo.html)
@@ -177,15 +177,15 @@ This is the relevant code:
177177

178178
```javascript
179179
// allow script elements
180-
var config = {
180+
const config = {
181181
ADD_TAGS: ['script'],
182182
ADD_ATTR: ['onclick', 'onmouseover', 'onload', 'onunload'],
183183
};
184184

185185
// Add a hook to sanitize all script content with MentalJS
186186
DOMPurify.addHook('uponSanitizeElement', function (node, data) {
187187
if (data.tagName === 'script') {
188-
var script = node.textContent;
188+
let script = node.textContent;
189189
if (
190190
!script ||
191191
'src' in node.attributes ||
@@ -195,7 +195,7 @@ DOMPurify.addHook('uponSanitizeElement', function (node, data) {
195195
return node.parentNode.removeChild(node);
196196
}
197197
try {
198-
var mental = MentalJS().parse({
198+
let mental = MentalJS().parse({
199199
options: {
200200
eval: false,
201201
dom: true,
@@ -212,7 +212,7 @@ DOMPurify.addHook('uponSanitizeElement', function (node, data) {
212212
// Add a hook to sanitize all white-listed events with MentalJS
213213
DOMPurify.addHook('uponSanitizeAttribute', function (node, data) {
214214
if (data.attrName.match(/^on\w+/)) {
215-
var script = data.attrValue;
215+
let script = data.attrValue;
216216
try {
217217
return (data.attrValue = MentalJS().parse({
218218
options: {
@@ -228,7 +228,7 @@ DOMPurify.addHook('uponSanitizeAttribute', function (node, data) {
228228
});
229229

230230
// Clean HTML string and write into our DIV
231-
var clean = DOMPurify.sanitize(dirty, config);
231+
const clean = DOMPurify.sanitize(dirty, config);
232232
```
233233

234234
### Hook to proxy all links [Link](hooks-link-proxy-demo.html)
@@ -264,7 +264,7 @@ DOMPurify.addHook('afterSanitizeAttributes', function (node) {
264264
});
265265

266266
// Clean HTML string and write into our DIV
267-
var clean = DOMPurify.sanitize(dirty);
267+
const clean = DOMPurify.sanitize(dirty);
268268
```
269269

270270
### Hook to proxy all HTTP leaks including CSS [Link](hooks-proxy-demo.html)
@@ -277,28 +277,28 @@ This is the relevant code:
277277

278278
```javascript
279279
// Specify proxy URL
280-
var proxy = 'https://my.proxy/?url=';
280+
const proxy = 'https://my.proxy/?url=';
281281

282282
// What do we allow? Not much for now. But it's tight.
283-
var config = {
283+
const config = {
284284
FORBID_TAGS: ['svg'],
285285
WHOLE_DOCUMENT: true,
286286
};
287287

288288
// Specify attributes to proxy
289-
var attributes = ['action', 'background', 'href', 'poster', 'src', 'srcset']
289+
const attributes = ['action', 'background', 'href', 'poster', 'src', 'srcset']
290290

291291
// specify the regex to detect external content
292-
var regex = /(url\("?)(?!data:)/gim;
292+
const regex = /(url\("?)(?!data:)/gim;
293293

294294
/**
295295
* Take CSS property-value pairs and proxy URLs in values,
296296
* then add the styles to an array of property-value pairs
297297
*/
298298
function addStyles(output, styles) {
299-
for (var prop = styles.length - 1; prop >= 0; prop--) {
299+
for (let prop = styles.length - 1; prop >= 0; prop--) {
300300
if (styles[styles[prop]]) {
301-
var url = styles[styles[prop]].replace(regex, '$1' + proxy);
301+
let url = styles[styles[prop]].replace(regex, '$1' + proxy);
302302
styles[styles[prop]] = url;
303303
}
304304
if (styles[styles[prop]]) {
@@ -312,8 +312,8 @@ function addStyles(output, styles) {
312312
* then create matching CSS text for later application to the DOM
313313
*/
314314
function addCSSRules(output, cssRules) {
315-
for (var index = cssRules.length - 1; index >= 0; index--) {
316-
var rule = cssRules[index];
315+
for (let index = cssRules.length - 1; index >= 0; index--) {
316+
let rule = cssRules[index];
317317
// check for rules with selector
318318
if (rule.type == 1 && rule.selectorText) {
319319
output.push(rule.selectorText + '{');
@@ -336,8 +336,8 @@ function addCSSRules(output, cssRules) {
336336
// check for @keyframes rules
337337
} else if (rule.type === rule.KEYFRAMES_RULE) {
338338
output.push('@keyframes ' + rule.name + '{');
339-
for (var i = rule.cssRules.length - 1; i >= 0; i--) {
340-
var frame = rule.cssRules[i];
339+
for (let i = rule.cssRules.length - 1; i >= 0; i--) {
340+
let frame = rule.cssRules[i];
341341
if (frame.type === 8 && frame.keyText) {
342342
output.push(frame.keyText + '{');
343343
if (frame.style) {
@@ -365,7 +365,7 @@ function proxyAttribute(url) {
365365
// Add a hook to enforce proxy for leaky CSS rules
366366
DOMPurify.addHook('uponSanitizeElement', function (node, data) {
367367
if (data.tagName === 'style') {
368-
var output = [];
368+
let output = [];
369369
addCSSRules(output, node.sheet.cssRules);
370370
node.textContent = output.join('\n');
371371
}
@@ -374,7 +374,7 @@ DOMPurify.addHook('uponSanitizeElement', function (node, data) {
374374
// Add a hook to enforce proxy for all HTTP leaks incl. inline CSS
375375
DOMPurify.addHook('afterSanitizeAttributes', function (node) {
376376
// Check all src attributes and proxy them
377-
for (var i = 0; i <= attributes.length - 1; i++) {
377+
for (let i = 0; i <= attributes.length - 1; i++) {
378378
if (node.hasAttribute(attributes[i])) {
379379
node.setAttribute(
380380
attributes[i],
@@ -385,12 +385,12 @@ DOMPurify.addHook('afterSanitizeAttributes', function (node) {
385385

386386
// Check all style attribute values and proxy them
387387
if (node.hasAttribute('style')) {
388-
var styles = node.style;
389-
var output = [];
390-
for (var prop = styles.length - 1; prop >= 0; prop--) {
388+
let styles = node.style;
389+
let output = [];
390+
for (let prop = styles.length - 1; prop >= 0; prop--) {
391391
// we re-write each property-value pair to remove invalid CSS
392392
if (node.style[styles[prop]] && regex.test(node.style[styles[prop]])) {
393-
var url = node.style[styles[prop]].replace(regex, '$1' + proxy);
393+
let url = node.style[styles[prop]].replace(regex, '$1' + proxy);
394394
node.style[styles[prop]] = url;
395395
}
396396
output.push(styles[prop] + ':' + node.style[styles[prop]] + ';');
@@ -405,7 +405,7 @@ DOMPurify.addHook('afterSanitizeAttributes', function (node) {
405405
});
406406

407407
// Clean HTML string and write into our DIV
408-
var clean = DOMPurify.sanitize(dirty, config);
408+
const clean = DOMPurify.sanitize(dirty, config);
409409
```
410410

411411
### Hook to sanitize SVGs shown via an `<img>` tag. [Link](hooks-svg-demo.html)
@@ -423,14 +423,14 @@ DOMPurify.addHook('afterSanitizeAttributes', function (node) {
423423
});
424424

425425
// Clean SVG string and allow the "filter" tag
426-
var clean = DOMPurify.sanitize(dirty, { ADD_TAGS: ['filter'] });
426+
const clean = DOMPurify.sanitize(dirty, { ADD_TAGS: ['filter'] });
427427

428428
// Remove partial XML comment left in the HTML
429-
var badTag = clean.indexOf(']&gt;');
430-
var pureSvg = clean.substring(badTag < 0 ? 0 : 5, clean.length);
429+
let badTag = clean.indexOf(']&gt;');
430+
let pureSvg = clean.substring(badTag < 0 ? 0 : 5, clean.length);
431431

432432
// Show sanitized content in <img> element
433-
var img = new Image();
433+
let img = new Image();
434434
img.src = 'data:image/svg+xml;base64,' + window.btoa(pureSvg);
435435
document.getElementById('sanitized').appendChild(img);
436436
```

‎demos/advanced-config-demo.html

+16-12
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,32 @@
99

1010
<!-- Now let's sanitize that content -->
1111
<script>
12-
/* jshint globalstrict:true, multistr:true */
13-
/* global DOMPurify */
12+
// Use strict mode
1413
'use strict';
15-
14+
15+
// Import DOMPurify if you're using modules, otherwise assume it's globally available
16+
// import DOMPurify from 'dompurify'; // Uncomment if using ES6 modules
17+
1618
// Specify dirty HTML
17-
var dirty = '<p kitty-litter="yes" french-fries="no">HELLO</p>\
18-
<style>*{x:expression(alert(1))}</style>\
19-
<ying><yang><bang>123456</bang></ying></yang>\
20-
<iframe/\/src=JavScript:alert&lpar;1)></ifrAMe><br>goodbye</p><h1>not me!</h1>';
21-
19+
const dirty = `
20+
<p kitty-litter="yes" french-fries="no">HELLO</p>
21+
<style>*{x:expression(alert(1))}</style>
22+
<ying><yang><bang>123456</bang></ying></yang>
23+
<iframe/\/src=JavScript:alert&lpar;1)></ifrAMe><br>goodbye</p><h1>not me!</h1>
24+
`;
25+
2226
// Specify a configuration directive
23-
var config = {
27+
const config = {
2428
ALLOWED_TAGS: ['p', '#text'], // only <P> and text nodes
2529
KEEP_CONTENT: false, // remove content from non-allow-listed nodes too
2630
ADD_ATTR: ['kitty-litter'], // permit kitty-litter attributes
2731
ADD_TAGS: ['ying', 'yang'], // permit additional custom tags
2832
RETURN_DOM: true // return a document object instead of a string
2933
};
30-
34+
3135
// Clean HTML string and write into our DIV
32-
var clean = DOMPurify.sanitize(dirty, config);
33-
36+
const clean = DOMPurify.sanitize(dirty, config);
37+
3438
// Grab innerHTML from returned clean body node
3539
document.getElementById('sanitized').innerHTML = clean.innerHTML;
3640
</script>

‎demos/basic-demo.html

+7-6
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@
99

1010
<!-- Now let's sanitize that content -->
1111
<script>
12-
/* jshint globalstrict:true */
13-
/* global DOMPurify */
1412
'use strict';
15-
13+
14+
// Assuming DOMPurify is globally available
15+
// import DOMPurify from 'dompurify'; // Uncomment if using ES6 modules
16+
1617
// Specify dirty HTML
17-
var dirty = '<p>HELLO<iframe/\/src=JavScript:alert&lpar;1)></ifrAMe><br>goodbye</p>';
18-
18+
const dirty = '<p>HELLO<iframe/\/src=JavScript:alert&lpar;1)></ifrAMe><br>goodbye</p>';
19+
1920
// Clean HTML string and write into our DIV
20-
var clean = DOMPurify.sanitize(dirty);
21+
const clean = DOMPurify.sanitize(dirty);
2122
document.getElementById('sanitized').innerHTML = clean;
2223
</script>
2324
</body>

0 commit comments

Comments
 (0)
Please sign in to comment.