Yesterday, we looked at how cross-site scripting attacks work, and outlined three approaches you can use to prevent them from happening. Today, we’re going to take a closer look at one of them: injecting plain text instead of HTML.
Let’s dig in!
Injecting plain text
One common approach to minimizing the risk of XSS attacks is to use properties that render plain text instead of HTML, such as
Element.innerText instead of HTML properties like
HTML injected using one of the plain text properties is automatically encoded.
// Get the node to inject your content into let app = document.querySelector('#app'); // Renders a string with encoded characters // This would show up in the DOM as an encoded string (<img src=x onerror="alert('XSS Attack')">) instead of as an image element app.textContent = `<img src=x onerror="alert('XSS Attack')">`;
If you need to add markup around the content, pair
Element.innerText with the
document.createElement() method, and inject it using one of the techniques from the previous lesson.
// Create your element let content = document.createElement('h1'); // Add your content content.textContent = `<img src=x onerror="alert('XSS Attack')">`; // Insert the content into the app app.append(content);
If you want to replace what’s already there, you can use
Element.innerHTML to wipe the parent container first.
app.innerHTML = '';
Injecting text is great for body content, but it does not protect you when using third-party data as the
href attribute on a link.
For that, you need to remove
Note: A savvy reader also pointed out that the
String.replace() approach to removing
Using properties that set plain text values are great if you’re only adding text, but if you’re adding a lot of markup around it, using
document.createElement() for every element can get tedious. Properties that inject HTML like
Element.outerHTML properties are so much easier.
Tomorrow, we’ll look at another approach you can use to selectively encode strings while still using HTML string properties like