DEV Community

Kristina Hodges (Voroteliak)
Kristina Hodges (Voroteliak)

Posted on • Edited on

Dangerous world of innerHTML

The innerHTML property is a part of the Document Object Model (DOM) that is used to set or return the HTML content of an element. Where the return value represents the text content of the HTML element. It allows JavaScript code to manipulate a website being displayed. More specifically, it sets or returns the HTML content (the inner HTML) of an element.

For beginners, innerHTML seems like the easiest and most elegant way to manipulate basic elements on the DOM. However, as your JS becomes more involved and your DOM increases in size, innerHTML will hurt performance and introduce security risks.

innerHTML is the source of a security risk: it can allow malicious actors to run JavaScript directly on your website. This can enable access to your backend server and any sensitive information stored there, such as user data and passwords.
In another scenario, a malicious script can be placed on your website and run every time a user accesses it, exposing your users directly to a security risk.

The vulnerability occurs when there is an opportunity for user input. For example, consider the following live code example:

Image description

The content of the input text field is printed beneath it when the user clicks submit. There are many use cases for this: chat apps, social media and profile editing.

Now, instead, of entering an innocent ‘about me’ text, enter the following: <img src="https://unsplash.it/200/200" onload="alert('User-run JavaScript!');" />.

And just like that, JavaScript is being run from the host website. In this case, we only create an alert. But the point here is what could be run.

Image description

  • ACCESS TO THE BACKEND SERVER
    A fetch request could be made to the backend server that would not be rejected as foreign because it is being made from the host website. This provides a gateway for access to everything stored on your server.

  • MALICIOUS SCRIPT TARGETING THE END-USER
    The opportunity for user-input could be use to place a script on the page that will run every time the page is accessed in the future. This script could scrape user information from the browser, including sensitive user information such as usernames and passwords.

Possible alternative

  1. Methods such as .createElement(), appendChild(), append(), and removeChild() allow for safe DOM manipulation without the unintended consequences of innerHTML (and innerHTML+=, more specifically). Unless you’re simply setting the text inside of an HTML tag, such as a

    or

    , stay away from innerHTML.

    It is recommended that instead of innerHTML you use:

    • Element.SetHTML() to sanitize the text before it is inserted into the DOM.

    • Node.textContent when inserting plain text, as this inserts it as raw text rather than parsing it as HTML.

    1. Use .textContent or .innerText where possible When rendering text only to the DOM it is not necessary to use .innerHTML. Instead, can use other methods available to us to write content to the DOM: .textContent and .innerText. When using these, if HTML is included in the input, it will not be rendered as such, but as text only.

    _Conclusion: _
    There are plenty of use cases where it is perfectly safe to use .innerHTML to render content to the DOM. For example, .innerHTML is very useful and safe when rendering static content (and dynamic content you are completely in control of) to the DOM.

    However, the security risks associated with .innerHTML occur when this is used when working with user input. In these cases: use .textContent or .innerText over .innerHTML when they can achieve the same outcome; if .innerHTML is necessary , employ a HTML sanitizer so purify user input.

Top comments (0)