The world of business-to-business enterprise software has always required a high level of custom per-client markup associated with branding and customization. In a SPA that generally means injecting markup in script.

Some posts tout frameworks like angular.js for safer rendering of this type. However, there is increasing pressure to shift away from frameworks towards vanilla script in many situations. There are benefits to performance, integration, maintenance, and so on. This is fueled by increasing size and complexity of existing frameworks, new major releases which depart radically from prior ones, and the constant churn in the JavaScript framework market.

What are the correct client-side security measures to inject markup using vanilla JS?

Please do not flag this as a duplicate of more general client-side XSS questions without the vanilla js requirement or the requirement for custom per-client (this could be termed untrusted, but unknown might be more accurate as it emanates from the client) markup.

  • 1
    there's a lot fewer risks than with a framework, but you still need to sanitize inputs and use a CSP – dandavis Aug 24 '16 at 21:12
  • Thanks for the timely responses Dandavis and Rook. So then is it correct to say that the use of style tags, innerHTML(), and so on are fine when the content within is determined by the client and can be sanitized on the server? – cage rattler Aug 25 '16 at 12:47
  • I'm amazed that four individuals are flagging this as a duplicate. I am trying to make sense of contradictions in the post you are referring to as well as specifying a use case not at all addressed in that post. Please do not rush to judgement in your reviews. – cage rattler Aug 25 '16 at 18:24

I'm not sure I read you right, but I think you want to insert untrusted HTML into the DOM using JavaScript? If so, these are my recommendations:

  • First of all you need a HTML purifier or sanitizer or whatever you want to call it, that removes any inline CSS or scripts. One example is Google Caja, but I am sure there are more options out there. Make sure to configure it to work the way you want it to. Blocking styles and scripts might not be the only thing you want to do. What about iframes? Forms? Links to strange protocols?
  • Now you need to use it on everything you insert into the DOM by e.g. using innerHTML(). One way to do that is to create a new function to use instead:

    Element.prototype.secureInnerHTML = function(input) {

    Note that .textContent and .setAttribute() are already safe, as they operate directly on the DOM and does not treat the input as a string of HTML. In general, it is a good rule to always use .textContent when markup is not needed.

  • Set a strict content security policy, disallowing all inline scripts and styles.

I'm not saying this will make you 100% secure, but at least it is a good start. Please note that since we have disabled inline CSS all styling has to be done using classes. If allowing inline CSS is a requirement, you have a much harder problem to solve.

  • Thanks Anders. Very helpful. By inline CSS you mean inline style attributes or style tags within the "untrusted" (client generated) markup. It's feasible to sanitize or perhaps remove that. However, is it correct to say that inline style, style tags in the head, innerHTML, and perhaps even things like eval() are NOT dangerous within our own static scripts? – cage rattler Aug 25 '16 at 12:56
  • I think my last sentence is unclear. My thought is that, for example, the innerHTML method might be safe when the markup to be injected is static and emanates from us. This might be more concise than adding elements and attributes one at a time. – cage rattler Aug 25 '16 at 13:05
  • With inline styles I mean any styles in the HTML document, and not in a separate CSS file. If it is static and you wrote it, it should be safe. But there is no way for the browser to know the source of the data, if it is trusted or not, so the best way to stay safe is just to turn off the ability to use any kind of inline styling (or scripts) with a CSP. – Anders Aug 25 '16 at 14:17
  • Not being able to use attributes like onclick and style might seem unpractical, but using those are probably not the best development pattern anyway. – Anders Aug 25 '16 at 14:19
  • In general onclicks and inline styles in markup are certainly not the best development patterns. Understood. Style tags generated on the server in the head of the document are in some cases the optimal way to transmit branding information. I do see some information here in the forums about security measures related to that, but I'm not sure how risky that particular style tag would be. Manipulating the style property of an element in script is sometimes required as well. Imagine trying animate a bouncing ball using CSS class names only. Does this incur risk? My guess would be no. – cage rattler Aug 25 '16 at 17:53

Not the answer you're looking for? Browse other questions tagged or ask your own question.