Version 0.2 - 2005-04-03
This is an idea for the client-side mitigation of Cross-Site Scripting (XSS). It's based on the same principle as "Content Restrictions" - that of the site owner specifying which scripts should be permitted and which not - but takes a slightly different and complementary approach. This is an updated version of an original proposal in a blog post.
An HTTP header, Script-Key, defines a random string or "key", and only script containing that string is allowed to execute. As the string will be different for every page load, static injected script would not be correctly labelled and therefore would not be permitted to run. Obviously, if it can't run, it can't detect the key and label itself in any way.
The text of the script just has to contain the key - in a comment is fine. So the labelling might work as follows:
Exactly how to label external scripts is still to be decided. It may be that the key has to be in the text of the external script file, or it may be that we would allow this:
Content-Type: text/html Script-Key: D3FC219A ... <script src="somescript.js"> // D3FC219A </script>
This latter approach has the advantage that the external script file can be the same for all users (static), but has the disadvantage that if an attacker can manipulate the "src" attribute, they can point it at their own script.
Exactly what the key is made up of, and how often and when it changes is completely up to the implementation. This gives maximum freedom to balance security and convenience. At one extreme, having a completely static key doesn't defend against much (except perhaps automated attacks against a large number of sites running the same software). At the other, having the key change with every page load would cause problems if external scripts are cached and so have an incorrect key.
Having the key set on a per-user basis, being stored in a database or even just being their session ID, has much to recommend it. This allows client-side caching to work much as before, and allows another server to take over serving pages to that user in a load-balancing situation.
Note that Script Keys don't have to be used in every part of a site. For example, purely static pages would not need to use them, because there's no risk of XSS.
So how does this approach compare with Content Restrictions? The two are complementary. Content Restrictions restricts by ability - so two blocks of code doing exactly the same thing would have the same abilities, and would work or fail in the same way. Script Keys allows you to distinguish between those two blocks, so that one works and one fails, but does not allow you to restrict the ability of either block once it's running.