1

I'm currently using this answer to escape my HTML before inserting it into a <div> using dangerouslySetInnerHTML in my app.

However, I noticed there are also libraries like DOMPurify, which purport to be the safer approach to escaping HTML. Except that it's approximately 1000x larger of a solution, so I'm wondering if it's necessary.

I notice that the first solution in my answer seems to work well enough. I tried entering <script>alert('a')</script> into the message box and it seemed to be escaped properly. For my purposes I'm only doing a couple simple markup transformations (bolding, italics, etc.).

Is what I'm doing enough, or do I need a more powerful solution like DOMPurify? I rather not add the dependency if it's not necessary.

Ryan Peschel
  • 11,087
  • 19
  • 74
  • 136
  • If you're escaping the HTML anyway, and you're using React, then why aren't you just inserting it normally as text? – Joseph Sible-Reinstate Monica Sep 14 '19 at 04:53
  • Just enabling some simple markdown transformations first. Like turning \*asdf\* into asdf. It's from user messages so I think I need dangerouslySetInnerHTML – Ryan Peschel Sep 14 '19 at 04:57
  • The question is are you willing to risk it? I don't think a single dependency being added is a big enough reason to justify the security risks the XSS attacks may pose. – Sagar Acharya Sep 14 '19 at 05:14
  • Well it seems like many people are already using the former solution judging by the amount of upvotes the response got. Was wondering if it's insecure. – Ryan Peschel Sep 14 '19 at 05:17
  • If you want to sanitize HTML tags only it's enough, otherwise you should opt for `DOMPurify` – matrixersp Sep 14 '19 at 05:22
  • @matrixersp: so in my case where the only place in my app I'm using dangerouslySetInnerHTML is for inserting into a div for user messages and applying the mentioned function, then I'm safe? – Ryan Peschel Sep 14 '19 at 05:35
  • @RyanPeschel I think it might cause issues in the text you pass to it, you should use `DOMPurify`, also they claim to be super-fast, so you don't have to care much about the performance – matrixersp Sep 14 '19 at 06:08
  • I don't care about the performance really, just about limiting dependencies. I have only one frontend dependency right now (React), and I'm trying to keep it that way. Also I'm confused because in your previous message you said it'd be enough but now you're saying you think it might not be enough. Looking for something more authoritative/definite. – Ryan Peschel Sep 14 '19 at 06:15
  • It depends on what you want to accept as user input. For example, blindly replacing `&`s by character entity references wouldn't work with user input containing "RESTful" URLs such as `http://example.com/whatever/x=1&y=2`. For handling cases like that (and also for the general case where you want to accept richly-formatted user input with tags), you'd need an HTML-ware sanitizer such as a full-blown SGML-based one. Simple solutions can't handle that; don' t know if `DOMPurify` can. – imhotap Sep 14 '19 at 07:41

1 Answers1

1

In its basic form? Yes, it is safe when used like this:

<p id="example"></p>
<script>
let escapedText = escapeHtml(userInput);
document.getElementById("example").innerHTML = escapedText;
</script>

However, once you start modifying the escaped text and adding your own HTML tags to it, you may accidentally introduce a vector to XSS. Here is an example with a link specified by user input:

<p id="example"></p>
<script>
let escapedLink = escapeHtml(userInput);
document.getElementById("example").innerHTML = `<a href="${escapedLink}">Click here</a>`;
</script>

This demonstrates two shortcomings:

  1. The attacker could set the link to javascript:alert(1) and achieve XSS.

  2. Legitimate links could not be inserted, as the HTML escape blocks the / character.

This is a simple example and there are many less obvious ways to mess up badly here. Using a good HTML purifier library, such as DOMPurify, not only helps against XSS and similar vulnerabilities, but also lets you implement or even accept user input for custom HTML.

rebane2001
  • 201
  • 1
  • 10