Folks often ask me how to build web applications without cross-site scripting (XSS) vulnerabilities, but I haven't really been able to find a reference that I'd be happy recommending. There are, of course, many different approaches you can use to build an XSS-free web application. This guide recommends a simplistic approach that works well for "single-document" web applications (like Gmail and Twitter) that use a single HTML document for the lifetime of the application.
Because complexity is the enemy of security, we approach the problem of eliminating XSS by simplifying how we handle untrusted data (by which we mean any information we retrieve from the network or from the DOM):
- Untrusted data MUST NOT be transmitted in the same HTTP responses
be static (and therefore cacheable for a long time).
- When transmitted from the server to the client, untrusted data
MUST be properly encoded in JSON format and the HTTP response MUST
have a Content-Type of application/json.
- When introduced into the DOM, untrusted data MUST be introduced using one of the following APIs:
Element.setAttribute(second parameter only)
That's it. If you follow those three rules, you stand a good chance of avoiding XSS. These rules are conservative. You can certainly build a secure web site that violates one or more of these rules. Conversely, these rules don't guarantee success. For example, they don't stop you from doing some dumb things:
// The textContent of a <script> element is active content. var scriptElement = document.createElement('script'); scriptElement.textContent = userData.firstName; // XSS! document.body.appendChild(scriptElement); // Some attributes (mostly event handlers) are active content: var imageElement = document.createElement('img'); document.body.appendChild(imageElement); imageElement.setAttribute('onload', userData.lastName); // XSS! imageElement.src = 'http://example.com/logo.png';
However, common sense should help you avoid those situations.