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.