_DOMPurify_ is one of the most trusted XSS (Cross-Site Scripting) sanitizers for web developers, used by thousands of websites to clean up user-generated HTML, SVG, and MathML. But in May 2024, a major security flaw—CVE-2024-48910—was found in DOMPurify. It’s a Prototype Pollution vulnerability, and it has serious consequences for web security.

This post gives a simple, clear explanation of what happened, how the bug can be abused, what the real risks are, and how to fix it—plus a real code snippet showing how this could be exploited in the wild.

What is DOMPurify?

DOMPurify is a well-known JavaScript library that takes untrusted HTML (like comments, messages, posts, etc.) and sanitizes it—removing anything that could be used to run XSS or other attacks. If you use a WYSIWYG editor or other HTML inputs, you probably use DOMPurify or something like it.

What is Prototype Pollution?

"Prototype Pollution" is a dangerous class of JavaScript vulnerabilities. In simple terms, it lets an attacker change the base object (the prototype) on which all other JavaScript objects are built. If an attacker can do this, they can potentially change how objects behave everywhere in your app, or insert new properties where you didn't expect them.

All objects in JavaScript inherit from Object.prototype. So, if the attacker can poison this root object, they can alter the behavior of code throughout your app, leading to privilege escalation, bypassing access controls, or running malicious code.

The Vulnerability (CVE-2024-48910) In DOMPurify

Affected Versions:

DOMPurify before version 2.4.2

Fix Version:
- 2.4.2

How it Happens

During the sanitization process, DOMPurify processes attribute names and values inside HTML elements. If an attacker can sneak in an attribute name like __proto__ or constructor, and DOMPurify doesn’t block it, these special names can trigger prototype pollution.

Let's look at a dangerous HTML payload

<img src="x" __proto__="hacked" />

If an app uses a vulnerable version of DOMPurify to sanitize this user HTML, it could end up setting a property called __proto__ on some internal object, leading to changing the entire prototype for all JavaScript objects on that page.

Exploit Example

Let's see a simplified Node.js test showing how a malicious user input could change the behavior of your app:

const createDOMPurify = require('dompurify');
const { JSDOM } = require('jsdom');

// Set up a DOM for DOMPurify in Node.js
const window = (new JSDOM('')).window;
const DOMPurify = createDOMPurify(window);

// Here's malicious HTML input that abuses prototype pollution:
const evilInput = '<img src="x" __proto__="hacked" />';

// Sanitize the input (using a vulnerable version)
const clean = DOMPurify.sanitize(evilInput);

// Check if global Object prototype is changed
console.log({}.hacked); // --> Should print "hacked" if vulnerable

If you run this code using DOMPurify prior to 2.4.2, you'll see that all objects now have a property hacked!

How does the fix work?

DOMPurify 2.4.2 and higher block attribute names like __proto__, constructor, and prototype during the sanitization process. Now, adding an attribute with a prototype-polluting name won't affect JavaScript objects outside of the cleaned HTML.

Double-check your app’s logic:

Make sure you are not relying on user-supplied property names elsewhere in your code—this is a recurring pattern for prototype pollution.

Monitor for similar patterns:

Prototype pollution often shows up when using object spread, Object.assign(), or merging objects from user input. Always sanitize input when creating or updating objects!

More Reading

- CVE-2024-48910 on NVD
- DOMPurify Release 2.4.2
- DOMPurify on GitHub

Final Thoughts

This is a textbook example of why no input should ever be trusted, not even attribute names in HTML. DOMPurify is a secure, trusted project, but even great code can have subtle bugs. Always keep your dependencies up to date, and look out for prototype pollution!
If you run a web application that lets users post any kind of HTML, this update is absolutely necessary. Prototype pollution can have wide-ranging, unpredictable consequences—don’t let your app be the next case study.


*Stay safe, keep dependencies updated, and always scrutinize user input—even in attribute names!*


If you have questions, check out the official DOMPurify issue tracker or talk to your security team.

Timeline

Published on: 10/31/2024 15:15:15 UTC
Last modified on: 11/01/2024 12:57:03 UTC