Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting 3.x branch ready for 3.0.9 release #913

Merged
merged 16 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

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

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.

Expand Down Expand Up @@ -413,6 +413,6 @@ Many people helped and help DOMPurify become what it is and need to be acknowled

## Testing powered by

<a target="_blank" href="https://www.browserstack.com/"><img width="200" src="https://www.browserstack.com/images/layout/browserstack-logo-600x315.png"></a><br>
<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>

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.
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.0.8",
"version": "3.0.9",
"homepage": "https://github.com/cure53/DOMPurify",
"author": "Cure53 <[email protected]>",
"description": "A DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG",
Expand Down
80 changes: 40 additions & 40 deletions demos/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ This is the relevant code:

```javascript
// Clean HTML string and write into our DIV
var clean = DOMPurify.sanitize(dirty);
const clean = DOMPurify.sanitize(dirty);
```

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

// Clean HTML string and write into our DIV
var clean = DOMPurify.sanitize(dirty, config);
const clean = DOMPurify.sanitize(dirty, config);
```

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

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

// Clean HTML string and write into our DIV
var clean = DOMPurify.sanitize(dirty, config);
const clean = DOMPurify.sanitize(dirty, config);
```

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

// Clean HTML string and write into our DIV
var clean = DOMPurify.sanitize(dirty);
const clean = DOMPurify.sanitize(dirty);
```

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

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

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

// Clean HTML string and write into our DIV
var clean = DOMPurify.sanitize(dirty);
let clean = DOMPurify.sanitize(dirty);
```

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

// Clean HTML string and write into our DIV
var clean = DOMPurify.sanitize(dirty);
const clean = DOMPurify.sanitize(dirty);
```

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

```javascript
// allowed URI schemes
var allowlist = ['http', 'https', 'ftp'];
const allowlist = ['http', 'https', 'ftp'];

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

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

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

// Clean HTML string and write into our DIV
var clean = DOMPurify.sanitize(dirty);
const clean = DOMPurify.sanitize(dirty);
```

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

```javascript
// allow script elements
var config = {
const config = {
ADD_TAGS: ['script'],
ADD_ATTR: ['onclick', 'onmouseover', 'onload', 'onunload'],
};

// Add a hook to sanitize all script content with MentalJS
DOMPurify.addHook('uponSanitizeElement', function (node, data) {
if (data.tagName === 'script') {
var script = node.textContent;
let script = node.textContent;
if (
!script ||
'src' in node.attributes ||
Expand All @@ -195,7 +195,7 @@ DOMPurify.addHook('uponSanitizeElement', function (node, data) {
return node.parentNode.removeChild(node);
}
try {
var mental = MentalJS().parse({
let mental = MentalJS().parse({
options: {
eval: false,
dom: true,
Expand All @@ -212,7 +212,7 @@ DOMPurify.addHook('uponSanitizeElement', function (node, data) {
// Add a hook to sanitize all white-listed events with MentalJS
DOMPurify.addHook('uponSanitizeAttribute', function (node, data) {
if (data.attrName.match(/^on\w+/)) {
var script = data.attrValue;
let script = data.attrValue;
try {
return (data.attrValue = MentalJS().parse({
options: {
Expand All @@ -228,7 +228,7 @@ DOMPurify.addHook('uponSanitizeAttribute', function (node, data) {
});

// Clean HTML string and write into our DIV
var clean = DOMPurify.sanitize(dirty, config);
const clean = DOMPurify.sanitize(dirty, config);
```

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

// Clean HTML string and write into our DIV
var clean = DOMPurify.sanitize(dirty);
const clean = DOMPurify.sanitize(dirty);
```

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

```javascript
// Specify proxy URL
var proxy = 'https://my.proxy/?url=';
const proxy = 'https://my.proxy/?url=';

// What do we allow? Not much for now. But it's tight.
var config = {
const config = {
FORBID_TAGS: ['svg'],
WHOLE_DOCUMENT: true,
};

// Specify attributes to proxy
var attributes = ['action', 'background', 'href', 'poster', 'src', 'srcset']
const attributes = ['action', 'background', 'href', 'poster', 'src', 'srcset']

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

/**
* Take CSS property-value pairs and proxy URLs in values,
* then add the styles to an array of property-value pairs
*/
function addStyles(output, styles) {
for (var prop = styles.length - 1; prop >= 0; prop--) {
for (let prop = styles.length - 1; prop >= 0; prop--) {
if (styles[styles[prop]]) {
var url = styles[styles[prop]].replace(regex, '$1' + proxy);
let url = styles[styles[prop]].replace(regex, '$1' + proxy);
styles[styles[prop]] = url;
}
if (styles[styles[prop]]) {
Expand All @@ -312,8 +312,8 @@ function addStyles(output, styles) {
* then create matching CSS text for later application to the DOM
*/
function addCSSRules(output, cssRules) {
for (var index = cssRules.length - 1; index >= 0; index--) {
var rule = cssRules[index];
for (let index = cssRules.length - 1; index >= 0; index--) {
let rule = cssRules[index];
// check for rules with selector
if (rule.type == 1 && rule.selectorText) {
output.push(rule.selectorText + '{');
Expand All @@ -336,8 +336,8 @@ function addCSSRules(output, cssRules) {
// check for @keyframes rules
} else if (rule.type === rule.KEYFRAMES_RULE) {
output.push('@keyframes ' + rule.name + '{');
for (var i = rule.cssRules.length - 1; i >= 0; i--) {
var frame = rule.cssRules[i];
for (let i = rule.cssRules.length - 1; i >= 0; i--) {
let frame = rule.cssRules[i];
if (frame.type === 8 && frame.keyText) {
output.push(frame.keyText + '{');
if (frame.style) {
Expand Down Expand Up @@ -365,7 +365,7 @@ function proxyAttribute(url) {
// Add a hook to enforce proxy for leaky CSS rules
DOMPurify.addHook('uponSanitizeElement', function (node, data) {
if (data.tagName === 'style') {
var output = [];
let output = [];
addCSSRules(output, node.sheet.cssRules);
node.textContent = output.join('\n');
}
Expand All @@ -374,7 +374,7 @@ DOMPurify.addHook('uponSanitizeElement', function (node, data) {
// Add a hook to enforce proxy for all HTTP leaks incl. inline CSS
DOMPurify.addHook('afterSanitizeAttributes', function (node) {
// Check all src attributes and proxy them
for (var i = 0; i <= attributes.length - 1; i++) {
for (let i = 0; i <= attributes.length - 1; i++) {
if (node.hasAttribute(attributes[i])) {
node.setAttribute(
attributes[i],
Expand All @@ -385,12 +385,12 @@ DOMPurify.addHook('afterSanitizeAttributes', function (node) {

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

// Clean HTML string and write into our DIV
var clean = DOMPurify.sanitize(dirty, config);
const clean = DOMPurify.sanitize(dirty, config);
```

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

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

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

// Show sanitized content in <img> element
var img = new Image();
let img = new Image();
img.src = 'data:image/svg+xml;base64,' + window.btoa(pureSvg);
document.getElementById('sanitized').appendChild(img);
```
28 changes: 16 additions & 12 deletions demos/advanced-config-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,32 @@

<!-- Now let's sanitize that content -->
<script>
/* jshint globalstrict:true, multistr:true */
/* global DOMPurify */
// Use strict mode
'use strict';


// Import DOMPurify if you're using modules, otherwise assume it's globally available
// import DOMPurify from 'dompurify'; // Uncomment if using ES6 modules

// Specify dirty HTML
var dirty = '<p kitty-litter="yes" french-fries="no">HELLO</p>\
<style>*{x:expression(alert(1))}</style>\
<ying><yang><bang>123456</bang></ying></yang>\
<iframe/\/src=JavScript:alert&lpar;1)></ifrAMe><br>goodbye</p><h1>not me!</h1>';

const dirty = `
<p kitty-litter="yes" french-fries="no">HELLO</p>
<style>*{x:expression(alert(1))}</style>
<ying><yang><bang>123456</bang></ying></yang>
<iframe/\/src=JavScript:alert&lpar;1)></ifrAMe><br>goodbye</p><h1>not me!</h1>
`;

// Specify a configuration directive
var config = {
const config = {
ALLOWED_TAGS: ['p', '#text'], // only <P> and text nodes
KEEP_CONTENT: false, // remove content from non-allow-listed nodes too
ADD_ATTR: ['kitty-litter'], // permit kitty-litter attributes
ADD_TAGS: ['ying', 'yang'], // permit additional custom tags
RETURN_DOM: true // return a document object instead of a string
};

// Clean HTML string and write into our DIV
var clean = DOMPurify.sanitize(dirty, config);

const clean = DOMPurify.sanitize(dirty, config);
// Grab innerHTML from returned clean body node
document.getElementById('sanitized').innerHTML = clean.innerHTML;
</script>
Expand Down
13 changes: 7 additions & 6 deletions demos/basic-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@

<!-- Now let's sanitize that content -->
<script>
/* jshint globalstrict:true */
/* global DOMPurify */
'use strict';


// Assuming DOMPurify is globally available
// import DOMPurify from 'dompurify'; // Uncomment if using ES6 modules

// Specify dirty HTML
var dirty = '<p>HELLO<iframe/\/src=JavScript:alert&lpar;1)></ifrAMe><br>goodbye</p>';

const dirty = '<p>HELLO<iframe/\/src=JavScript:alert&lpar;1)></ifrAMe><br>goodbye</p>';
// Clean HTML string and write into our DIV
var clean = DOMPurify.sanitize(dirty);
const clean = DOMPurify.sanitize(dirty);
document.getElementById('sanitized').innerHTML = clean;
</script>
</body>
Expand Down
Loading
Loading