How to Display User Input Safely (textContent)

How to Display User Input Safely (textContent)

Anyone that’s ever created a form, comment section, or search box using JavaScript will have had to show something that a user typed on a web page.

Well, it seems like a no-brainer, but one thing I’d like to stress is that you should never use user input as HTML, unless you have a good reason and the proper security measures.

For instance, someone may enter a regular comment, and another may enter a string with some HTML tags or code to exploit your site. However, if your JavaScript takes that input and processes it in an incorrect way, it can result in a security problem called Cross-Site Scripting (XSS).

Fortunately, there is a simple solution in JavaScript to prevent the common cause of this problem. The property textContent is used to show a user’s input as text without relying on the browser to render it as HTML.

Let’s see how it works, how it differs from the old innerHTML and how it can be used in your own projects.

What is textContent in javaScript?

The HTML property textContent can be used to retrieve or modify the content of an HTML element with JavaScript.

The primary benefit of this is that the browser interprets the value you set as text. Does not convert HTML-like strings to elements.

For example:

const message = document.getElementById("message");

message.textContent = "<h1>Hello World</h1>";

This code should be used to make a heading, but it doesn’t. The following text will appear on the page of the browser:

<h1>Hello World</h1>

Notice how the angle brackets and tags are still there because textContent does not interpret the string as HTML.

It is a great option for displaying content directly from users such as comments, user names, messages, etc.

So, why is it important to display user input safely?

Information that is entered by the user may include more than just ordinary text. A person could inadvertently enter HTML tags, or they could deliberately put content in your site that is designed to take advantage of a vulnerability.

Typically, the issue begins when an application processes that input and places it on the page as HTML without proper processing.

For instance, this string:

<script>alert('XSS')</script>

Browsers might interpret HTML if an application puts user controlled content into a HTML parsing context. This may lead to Cross-Site Scripting (XSS) vulnerability, depending on how the content is inserted and upon the security protection measures implemented.

XSS can be used to execute malicious JavaScript code in a victim’s browser with the security context of the compromised site.

That’s where the textContent comes in handy. If you set a string to an element’s “textContent” property, the browser interprets the string as a text, not HTML.

This is an easy method to prevent a common HTML injection problem for content that should be plain text.

How to safely display user input, using textContent

Let’s create a little example of what you can do with textContent in a real JavaScript project.

Step 1: Create an HTML Form

Go with a simple form that visitors can use to enter a message. We’ll also add a paragraph to display whatever they submit.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Safe User Input</title>
</head>
<body>

    <h1>Enter Your Message</h1>

    <form id="messageForm">
        <input
            type="text"
            id="userInput"
            placeholder="Write your message"
            required
        >

        <button type="submit">Submit</button>
    </form>

    <p id="output"></p>

    <script src="script.js"></script>
</body>
</html>

There are three sections to the form: an input, a submit button, and a blank paragraph where the message will be displayed.

We will link these elements together and process the text that is entered using JavaScript.

In Step 2, you will read in the user input using JavaScript.

First, we must choose the HTML elements with which we will be working before presenting the message.

You can add the following code to your script.js file:

const form = document.getElementById("messageForm");
const userInput = document.getElementById("userInput");
const output = document.getElementById("output");

Here each variable is a different element of the page.

  • form is the form in which the input field is contained.
  • userInput provides access to the textbox in which the visitor enters a text.
  • The value of output is the address of the paragraph that we will be printing the message on.

These references simplify the handling of the form, without needing to search for the same elements every time.

Step 3: Display the Input Using textContent

Let’s get the form moving now.

Copy and paste this code below the last example:

form.addEventListener("submit", function (event) {
    event.preventDefault();

    const message = userInput.value;

    output.textContent = message;
});

That’s all you need to display the submitted message as plain text.

The background:

  • The function will be executed when the visitor submits the form, via addEventListener("submit", ...).
  • If you use event.preventDefault(), the browser will not submit the form the usual way.
  • The result with the text you type into the textbox is stored in the variable userInput.value.
  • The message will be shown in the paragraph using the style output.textContent = message.

The important part is the last line. If there is anything HTML-looking in the message that is sent, the browser won’t read it as HTML in this assignment.

Step 4: Test the Code

Try typing in a regular text, for example:

Hello, welcome to my website!

Once you have clicked Submit, the message will be displayed in the paragraph below the form.

Try typing in this string:

<img src=x onerror=alert('XSS')>

The browser shows all the string as text with the textContent property. It doesn’t create an image element or run the event handler contained in that string.

This simple test makes it apparent why you may use textContent whenever you want to display submitted content without having to process it as HTML.

textContent vs innerHTML: Which Is Safer?

There are a few ways to update the content of a webpage with JavaScript. There are two popular properties: textContent and innerHTML, both of which receive different kinds of strings.

The main difference is that value is treated as a text attribute with textContent and as HTML with innerHTML.

Let’s do a quick comparison:

FeaturetextContentinnerHTML
Allows display of plain textYesNot necessarily
Extracts HTML stringsNoYes
Can build elements from an HTML stringNoYes
Suitable for displaying untrusted textGenerally yesRequires careful handling
No risk of HTML injection assigned contentNo HTML parsing in assigned contentMay inject HTML

For example, with innerHTML:

const output = document.getElementById("output");

output.innerHTML = userInput.value;

This tells the browser to interpret the supplied string as HTML. The application can be susceptible to HTML injection or XSS if the string contains unsafe mark-up.

Then compare it to:

output.textContent = userInput.value;

In this case the browser prints the value, but does not assume it’s HTML.

The simplest guideline to follow is: Use textContent for plain text. Do not use innerHTML unless you really need to create HTML and take the necessary security precautions.

Prevent all XSS Attacks with textContent?

While textContent can be handy for rendering untrusted content as plain text, it is not a solution to all the security issues faced by a JavaScript application.

This will depend on the intended use of the data.

1. HTML Text Content

If you wish to post a visitor’s comment,

document.getElementById("comment").textContent = userComment;

This is a good method as the comment is already in a text format. HTML tags or script-like strings in the value won’t be parsed as HTML by this assignment.

Usernames, search words, and regular messages can be used with the same method.

2. HTML Attributes

Values set using textContent are not necessarily safe for all HTML attributes.

For instance, an application could require to specify the attributes of an element in response to user input. Some attributes, especially event-handler attributes, can result in security problems if not used properly.

Apply the right DOM properties and methods; validate values based on their use. Do not store untrusted strings in code that can be executed as events.

3. URLs

Special attention should be paid to URLs.

For example, a user given URL may include a scheme as javascript: Just setting an untrusted value to the href property of a link does not make the link safe.

Before employing a URL for navigation, check the format of the URL and handle only the protocols required for your application, for example only https:.

4. JavaScript and CSS Contexts

Numbers in JavaScript or CSS do not need to be treated like numbers in a paragraph.

Do not mix untrusted input with executable code, event-handler strings or unsafe CSS. Separate data from code and apply security controls that are appropriate to the situation.

The lesson to be learned here is that while textContent is a good option for displaying simple text, other destinations require their own protection.

In this section, you can find the best practices to using textContent securely.

Using textContent is a good starting point. There are a couple more habits that you could be doing when the user enters input within your app.

Use textContent for simple text content

Typically you don’t need to parse the value as HTML if you want to show a username, comment, or message.

For example:

const username = document.getElementById("username").value;

document.getElementById("welcomeMessage").textContent =
    "Welcome, " + username + "!";

If someone types in HTML-like characters in their username, the browser will show the characters as text.

Don’t use innerHTML when it’s not necessary.

In many cases, you don’t need to use innerHTML when you want to change something on a webpage, but it’s easy to fall into the trap of doing so.

When you are showing a string, it’s easier to use textContent and not try to parse a string as HTML. Don’t render HTML when it is not necessary.

Confirm Input as needed

There are certain input types required in some fields. For instance, you may wish that a username be held to a specific length, or that an e-mail field should adhere to a particular format.

Input validation can be used to help ensure those rules, but it is not the only mitigation for XSS. Even if it’s been validated, data should be treated in a safe manner when it is displayed on a webpage.

Use Safe DOM Methods.

Users will submit content to which you need to create new HTML elements. You can do that without inserting their text as HTML.

For example:

const comment = document.createElement("p");

comment.textContent = userComment;

document.getElementById("comments").appendChild(comment);

This code will create a paragraph, set the comment as plain text and append the paragraph as a new comment.

The text of the comment is not interpreted as HTML as it is assigned via the property textContent.

Keep Security Context in Mind

Not all strings are suitable for displaying in a paragraph are suitable for use in a URL, event handler or other sensitive context.

When you use data that users provide, think about the place where it will be used and how the browser will interpret it.

Use a trusted HTML sanitizer that only lets in the markup you require when you need to show user-provided rich text, like user-provided HTML-formatted comments. The replacement of textContent should not be used instead of a sanitizer that’s designed to render HTML.

Common Errors to Steer Clear of

While you know how to use textContent, there are a few common pitfalls that you might want to be aware of.

The first error is getting rid of innerHTML for Plain Text.The first error is to replace innerHTML with Plain Text.

Consider this line:

output.innerHTML = userInput;

This might be convenient, but the browser assumes that the assigned value is HTML. Use: if you want only to display the message of the user:

output.textContent = userInput;

This keeps the content as text, rather than markup.

Mistake 3: Sanitizing every input before using it in the textContent.Mistake 4: Sanitizing all inputs before using them in textContent.

It’s not generally necessary to HTML-safely sanitize a string only for it to be displayed using textContent. In the context, the browser already interprets the assigned value as a text.

Note that doesn’t imply that you can’t bother about all the input checks. Length restrictions, rejecting invalid data or other rules needed by your app may still be necessary.

Your Error # 3: Security All Data Destinations with textContent.

For example, using the same input, two different ways of using it:

element.textContent = userInput;

// This is a different security context:
link.href = userInput;

The first line prints the input, as text. The second relies on it as a URL for a separate validation.

Never assume that a value is safe in one location and all others are equivalent.

Mistake 4: Using textContent when you want to use Visual Formatting

You cannot use the property textContent to make HTML tags into formatting.

Suppose that someone types:

<strong>Hello</strong>

The word is not bold, but is displayed in bold in the browser.

This is what you’re supposed to do. For applications that require rich-text formatting, implement a well-designed HTML-rendering procedure and a suitable sanitizer.

Frequently Asked Questions

Will the user input be safe to display in textContent?

Yes. If the text content is HTML, it’s best to use the DOM innerHTML property, but if it’s a regular text string, it’s OK to use textContent.

Is textContent better than innerHTML?

Use textContent when you need to show plain text; this will help prevent injection issues when inserting untrusted strings with innerHTML.

Does textContent remove HTML tags?

No. It doesn’t remove tag-like text from the string. Rather, it shows those characters as if they were not HTML.

For instance, this line, <b>Hello</b>, will be printed as <b>Hello</b> and not as bold text.

Is it necessary to sanitize user input before using textContent?

The textContent property already ensures that the value assigned to it is not HTML and thus not interpreted.

In other applications, however, you might need validation for applications’ requirements or extra protection when using the same data.

Is textContent the answer to all your XSS vulnerabilities?

No. It guards the particular case in which an unverifiable value is used as a text. There are certain elements of the Web that need special handling, namely URL, JavaScript, CSS and purposeful HTML.

Conclusion

It’s not hard to safely show user input. When creating a comment section, form, or any other feature that displays text entered by visitors, the textContent property of JavaScript is an easy and reliable starting point.

It does not instruct the browser as to how to render the value it is assigned as HTML.Does not request the browser to render the value assigned as HTML, unlike innerHTML. This is helpful for displaying untrusted content in plain text and can help minimize one route to the potential vulnerability of XSS.

Use the most appropriate security measures for different contexts – for plain text, use textContent; for the validation of data, use it when required by your application. Though simple, they can render your JavaScript applications more secure without introducing excessive complexity.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *