Tuesday, November 6, 2007

The JavaScript security model - "Same origin policy"

pencil icon, that"s clickable to start editing the post

I'm aware of what Cross-site scripting (XSS) are and that browsers implement JavaScript as to avoid it, but I've never known exactly what the rules are. I decided it was time to find out so I started searching for the specifications (knowing that there are several of them):

I found nothing. Maybe I used the wrong keywords but it was an dead end. Rather disappointed I started searching the the 'JavaScript security model' and through that I finally found what it was called Same origin policy. I though I might go with the definition on wikipedia like I've done many times. Voilá there waa a definition:

The term "origin" is defined using the domain name, protocol and port. Two pages belong to the same origin if and only if these three values are the same.

But looking at the examples I could see that some of them failed because of Different host. Not clear, so I looked at the Mozilla resource for same-origin:

The same origin policy prevents document or script loaded from one origin from getting or setting properties of a document from a different origin. The policy dates from Netscape Navigator 2.0.

Mozilla considers two pages to have the same origin if the protocol, port (if given), and host are the same for both pages.

Even more simply explained by Mitch Stoltz in a presentation on Security in Mozilla (2002) in the slide Security Policies: Same-Origin with the formula: Hostnames are compared string-wise.

Update -11/8/2007: I'm picky about the words domain name and hostname (fully qualified). To me they are NOT the same - yes, in rare occasions the are interchangeble - but when wikipedia on same origin states: "The term "origin" is defined using the domain name, protocol and port." i disagree like the Mozilla explanation. As a further side note, the Wikipedia article on Hostname has in the section on "Internet hostnames":

On the Internet, a hostname is a domain name assigned to a host computer. This is usually a combination of the host's local name with its parent domain's name. For example, "en.wikipedia.org" consists of a local hostname ("en") and the domain name "wikipedia.org". This kind of hostname is translated into an IP address via the local hosts file, or the Domain Name System (DNS) resolver. It is possible for a single host computer to have several hostnames; but generally the operating system of the host prefers to have one hostname that the host uses for itself.

Any domain name can also be a hostname, as long as the restrictions mentioned below are followed. So, for example, both "en.wikimedia.org" and "wikimedia.org" are hostnames because they both have IP addresses assigned to them. The domain name "pmtpa.wikimedia.org" is not a hostname since it does not have an IP address, but "rr.pmtpa.wikimedia.org" is a hostname. All hostnames are domain names, but not all domain names are hostnames.

I don't agree, but I could be the odd one

Compared to IE6+ cookie policy

Some months ago I looked at how IE6+ had implemented P3P to control cookie policies (Party cookies - first or third-context) and I guess I had expected the JavaScript policy to be close to this, but it turned out very different, with IE6+ being more lax with the concept of minimal domain.

Wrap up

Update (11/8/2007): The most important thing is that I found out what policy is. There's is a way to ajust to i by setting document.domain in both documents to the same parent domain. So there's an easy trick for hosts on the same parent domain but still no cross domain. My current best guess is to use the CNAME trick again like with cookies, that is you create a CNAME record for someNewHost.on.my.domain.tld to reference the hostname of the cross site. This should work since the comparison is done on the immediate name. It's faily easy if you like adding CNAME records to other sites (domains), and the other site can be called with that hostname and lastly insert the correct value to document.domain. There are even more advanced ways like doing the ajustment by communicating between two iframes by fragment identifiers (and other one).

I am surprised that the description of same-origin policy is not part of the specifications and is left for those that implement it in browsers, but on the other hand it fits nicely with my misconception on the world of JavaScript.

After I wrote this post I found and brilliant article on the subject of same origin a the related security hacks called Same-Origin Policy Part 1: Why we’re stuck with things like XSS and XSRF/CSRF.