We will go through the basic techniques of defending against cross-site scripting. This is by no means a comprehensive list of defenses against cross-site scripting, but it should be enough to get you started.
We can parse the user's input using various techniques. Since we are talking about JavaScript in this book, we can apply the following JavaScript function to prevent the execution of malicious code:
function htmlEntities(str) {
return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
}This function effectively strips the malicious code from the user's input and output as normal strings. To see this function in action, simply refer to the source code for this chapter. You can find this function in use at python_server/templates/todos_secure.html. For ease of reference, the code snippet is being applied here as follows:
function htmlEntities(str) {
return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
}
function todoTemplate(title, body, id) {
var title = htmlEntities(title);
var body = htmlEntities(body);
var snippet = "<div id=\"todo_"+id+"\"" + "<"<h2>"+title+"</h2>"+"<p>"+body+"</p>";
var delete_button = "<a class='delete_item' href='#' id="+id+">+">delete</a></div><hr>";
snippet += delete_button;
return snippet;
}Notice that the to-do item is first being escaped and returned as an HTML template for our app to insert into the browser screen.
There are times when some HTML tags are allowed to be used for users. Some libraries help us do this, such as Google Caja (http://developers.google.com/caja).
Another approach is to make use of auto-escape or similar utilities to escape the input first. For instance, instead of using Ajax to get the output, you can simply generate the output from the server side. In Tornado's case, you can make use of the autoescape function. You can learn more about it at http://tornado.readthedocs.org/en/latest/template.html.
There are other ways and forms of protection as well:
HTTP only flags in your cookies so that JavaScript won't be allowed to access them.