As we know, developers are responsible for correctly escaping/validating data provided by the user before rendering or storing them. However, we must agree that it's relatively easy to forget a single input among hundreds, and finally get your web-app exploited by a XSS. Or haven't you met someone that got his/her site exploited by XSS?
Even Twitter and Orkut recently suffered from XSS. And I'm not here to blame anyone.
Suppose your browser supported whitelisting DOM elements. These whitelisted elements are the only elements allowed to execute JavaScript. You quickly realise that sounds insane because it's impossible to keep your preferred website working properly if you have such a generic whitelist. And you're correct!
But now suppose that HTML and JavaScript engines supported a syntax to allow you to whitelist elements of your own website. For example:
<head>
<script type="text/javascript">
document.allowJavaScript(['div.item', '#list', 'a.navigate']);
</script>
</head>
This doesn't solve the problem of rendering <script>
tags in the middle of a DOM tree, but this is much easier to solve, I suppose.
Besides my previous point, what kind of problems or flaws do you see in the described solution?
UPDATE 1: only the head element should be trusted to invoke allowJavaScript
.
UPDATE 2: hopefully, the following snippet explains my idea a bit further:
<html>
<head>
<style>
div.outer { background-color: #aaa; width: 200px; height: 100px; }
div.inner { background-color: #5ff; width: 100px; height: 50px; }
ul { list-style-type: none; }
li { background-color: #bbc; border: 1px solid #fff; float: left;
width: 100px; height: 30px; }
</style>
<script type="text/javascript">
document.allowJavaScript(['div.outer', '#list', 'a.test']);
function register_events() {
var list = document.querySelector('#list');
list.onclick = function() { alert('list'); }
var example1 = document.querySelector('#list li:nth-of-type(1)');
example1.onclick = function() { alert('example 1'); }
}
window.onload = register_events;
</script>
</head>
<body>
<div class="outer" onclick="alert('outer');">
<div class="inner" onmouseover="alert('inner');">
</div>
</div>
<a class="navigate" href="#" onclick="alert('a');">click me</a>
<ul id="list">
<li>example 1</li>
<li>example 2</li>
</ul>
</body>
</html>
This should NOT allow execution of:
alert('inner')
-> we allowdiv.outer
, but none of its child elements;alert('example 1')
-> we allow#list
, but none of its child elements;alert('a')
-> we allowa.test
, nota.navigate
;