4

What are the reliable and stable client-side JavaScript libraries for XSS prevention and why? It would be very beneficial if you could provide details like:

  • browser support
  • conformity to any standards (like OWASP guidelines)
  • their approach (e.g. minimal escaping, blaclisting/whitelisting)
  • any tests they passed (are there such industry standard XSS tests?)
  • is it actively maintained for recently discovered threats

You can add more items to the list.

4 Answers 4

3

First and foremost, XSS is an output problem - one which almost always affects the server's output, and is therefore patched on the server. XSS allows for an attacker to inject JavaScript, which is used to hijack the browser and perform any action as the victim.

The only viable client-side XSS mitigation is having a strict content-security policy (CSP) which disallows inline injections. The CSP is a set of server-defined rules that are enforced by the browser and is used to limit the execution of JavaScript. The CSP is a new and very powerful tool for shutting down XSS.

Another common approach to client-side XSS mitigation is to use AngularJS templates. A secure template language like AngularJS will mitigate XSS by neutralizing executable code which was intended to be displayed as text. This is a great approach to developing secure applications. However an application that uses AngularJS cannot protect against API calls that are vulnerable to XSS, only the CSP can do that.

AngularJS + CSP will make an application very difficult to exploit with XSS, but nothing is 100%. There is still the possibility of DOM based XSS and Cross-site attacks in Flash, which are both very similar to each-other. There is no blanket mitigation here, not even a Web Application Firewall (WAF) can stop these attacks - they are perfect and widespread.

2
  • Interesting information in your answer. However, if you could expand on why AngularJS templates can mitigate XSS, that would be great. What do they provide that other technologies fail to do? Your link is a bit confusing too because it ends up showing how they can be exploited, which blunts the point you are making for the uninitiated. Aug 12, 2016 at 8:34
  • @SilverlightFox I provided a link which describes template sand-boxing. But, templates mitigate XSS by separating executable code and data. Nothing is 100%, and if someone tells you it's 100% effective, then you are being sold snake oil.
    – rook
    Aug 13, 2016 at 1:28
1

As @rook's answer mentions, the only way that JS can protect against XSS is when using a framework (like Angular) that retrieves all dynamic page content via JS (usually using XmlHttpRequest) and then safely injects it into the page. As @GeorgeMauer points out, you (or your framework) can safely do this inject-into-the-page step using the textContent/innerText property of a DOM element, but then you lose the ability to specify any kind of dynamic formatting at all. Sometimes this is OK, sometimes it's not.

Client-side script can never protect against XSS injections going to the server. As the name suggests, XSS is often injected across sites, so your client-side code can't catch the injection because it's not even happening on your site (and thus your client-side code isn't running). Stored XSS is often injected from within the target site, but again, client-side validation won't help; the attacker can (and will) either disable the validation (they control the client; they control the client-side code that runs on it) or just custom-create the malicious HTTP request (POST or whatever) using a tool like curl or Burp Suite.

Similarly, client-side code can't protect against malicious HTML/JS content returned by the web server in response to a page request. By the time the sanitization checks (or whatever) are executing, so is the malicious code; it's too late! You have to do all your validating/escaping/whatever before the code hits the rendering/JS engine. There's only two ways to do that: run it client-side on JS strings which you then later add to the page content (this is how Angular and friends work, but they are not foolproof) or do it on the server.

  • Escaping? Great idea, you should have your server do that!
  • Blacklisting? Terrible idea, waste of time and a false sense of security.
  • Whitelisting? A good input validation technique; you should have your server do this.
  • If you do your XSS-prevention server-side, then the browser doesn't know or care. All browsers understand URL, HTML, and JavaScript escapes.
  • There are no "standards" around XSS safety, any more than there are "standards" around native code memory safety.

Similarly, there's no battery of tests that are worth the time it took to compile them. You can throw every automated scanner you want at your code, but if you only built your protections to the level necessary to beat those scanners, and intelligent attacker will probably bypass them. I do it all the time. Scanners have only two outputs: vulnerable and maybe vulnerable. They cannot tell you that you're safe.

Don't go for minimal coverage. Don't try to get cute and do everything client-side; even if you're using something like Angular, operate on the assumption that it's vulnerable and do your input validation and output encoding on the server! Rather than trying to be safe against known threats and hope that you get updated protection against future ones, have your server only return code that is guaranteed to be safe. By all means run a scanner, but also hire somebody who knows what they're doing to pentest it for real, if you're concerned about security.

5
  • So doesn't this answer completely contradict George Mauer's above? Isn't refraining from the use of innerHTML and so on just a minor inconvenience to the hacker at best - sort of closing a screen door? Aug 24, 2016 at 15:34
  • @AvramLavinsky: George's answer isn't about refraining from innerHTML, it's about setting all (non-static) content using textContent/innerText. This means you can't return user-controlled content from the server as HTML. Most web apps never need to set innerHTML at all. Either the server sends all the page content as HTML (in which case it had better have all user input filtered and/or escaped), or the server sends static templates and dynamic content is only sent as text in XHR responses, and injected into the page via client-side code (via textContent or building DOM elements).
    – CBHacking
    Aug 24, 2016 at 19:24
  • Thanks CBHacking. Understood. Sounds like you're saying innerHTML isn't really adding much risk, but since many settings don't require it, it should be avoided in those settings. As I commented to Rook above, in business-to-business enterprise software we have loads of dynamic content that includes markup. Any insight in that context? Aug 24, 2016 at 19:48
  • I mean, innerHTML is exactly as dangerous as returning the same content from the server with Content-Type: text/html. Using it isn't inherently vulnerable, but it sure isn't any kind of "anti-XSS measure", which is what the question asks about.
    – CBHacking
    Aug 25, 2016 at 0:04
  • @AvramLavinsky if you don't need to set innerHTML, just set textContent and you will be 100% protected in that component. However, a lot of stuff needs innerHTML for example if user input allows <b> or <img> tags. Then you need to do all the other stuff. I still don't think that there's anything 100% that you can do on the server, but I'm not sure of that Aug 30, 2016 at 23:18
0

How about only ever placing text into the DOM by setting textContent on a DOM element?

Pros:

  • Will prevent XSS 100% of the time.
  • 100% browser support (older versions of IE call it innerText but easy enough to shim).
  • No library needed at all.

Cons:

  • You have to actually do this or use a framework that does this.
  • You cannot place any html into the text, including inline markup like <em>.

As a side note, I'll mention that many people think this means that you can create an element, set textContent, and then grab innerHTML in order to sanitize text. This is not the case.

2
  • The world of business-to-business enterprise software has always required a high level of custom per-client markup associated with branding and custom engineering. In a SPA that generally means injecting markup in script. Simply using innerText or textContent is not sufficient. Aug 24, 2016 at 15:08
  • You're not wrong, but I'm not sure about the assumption that this is not sufficient for customization. For a full CMS this can certainly be a problem (though not necessarily) but anything short of that can often be handled with css. Sometimes the tradeofs aren't worth it, but it is quite possible. Aug 24, 2016 at 20:53
0

I will help by stating that you should not use a session management library and an architecture that are based upon passing sensitive data (like a session ID) to the client and storing it in the HTML5's localStorage or non httpOnly cookies, this is the quote from OWASP:

Data stored in this object will persist after the window is closed, it is a bad idea to store sensitive data or session identifiers on this object as these can be accesed via JavaScript. Session IDs stored in cookies can mitigate this risk using the httpOnly flag.

Using cookies with the httpOnly flag will prevent (in browsers that support it) the risk that any script will pull that data from the localStorage. There are still other risks of course - but this will also help.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .