Almost a year ago, we noticed that uploading images with the "basic" uploader while creating an auction on eBay doesn't work. It appears to just hang, but the error console reveals that it fails with a security exception.
The upload itself happens in a popup window where document.domain has been set, but only to the host name of the server – basically doing document.domain=document.domain. While this looks like a no-op, it actually changes the security origin from "all pages sent from cgi5.ebay.com" to "all pages that set their document.domain to cgi5.ebay.com". The opener page does not set document.domain but comes from the same server. Opera would traditionally consider them same origin and let the popup and opener communicate. However, in March 2008 we noticed a comment in WebKit's source code claiming this is a security hole in Opera – while I don't entirely agree with that we nevertheless aligned our security policy with the others. And thus we broke eBay's image upload!
After looking at the eBay issue last autumn and noticing the nasty and confusing browser-sniffing in the code that sets document.domain, we decided it was probably eBay's fault and left it with the Open The Web/Developer Relations team as OTW-5637, where it's been in limbo for months after initial attempts at getting through to the right people – no small task with a site and company as large as eBay. I asked in the bug why it works in other browsers, but the browser sniffing appeared to be sufficient explanation so back then I didn't continue the analysis.
Yesterday, the question came up again, and I tested with Chrome and Firefox. (As an aside, both have the annoying habit of making the address field of the popup read-only if the script wants – Opera ignores this user-unfriendly command.. So before testing the upload popup I used a simple bookmarklet
to make sure the address bar would be editable.)
With the popup open, trying simple bookmarklets like
quickly revealed that all browsers consider the popup and the opener different origins. Yet other browsers allowed the callback that modified the DOM in the opener to show the uploaded image!?
eBay relies on an inconsistency in the security policy of other browsers:
The code in the popup will try to pass the URL to the opener to show the image thumbnail in the page, then close the popup. To do so it calls methods in the opener. It has access to these methods because it stored a pointer to them before document.domain was set – so it was allowed to reference them.
In Opera, when the callback tries to modify the DOM and show the image, a security check in the DOM kicks in. This is why the script stops with a security error – Opera is the only browser that notices that the running script has a different origin than the document whose elements we're manipulating. This test shows the different behaviour.
Chrome and Firefox happen to not do a security check in the relevant DOM code. They do treat the popup and the opener as being from different origins, but their security policy has a convenient inconsistency that allows this callback.
So, the state of this issue:
- Opera enforces the same-origin security policy in code points in the DOM where other browsers apparently do not
- eBay's code requests really inconsistent security behaviour from browsers – wanting random pages to be different origin and relying on apparent bugs in browser security policies
- Other browsers' implementations appear to be safe enough against actual exploits, though confusing and inconsistent
Changing security policy implicitly by removing some of our same-origin checks is a risky fix :yikes: . I can't think of a way to exploit what the other browsers are doing, but we'd certainly prefer staying consistent.. I'll probably look at a site-specific browser.js patch first, to make eBay work while we think about it.
Reader opinions welcome – who has the best suggestion for how we should resolve this conundrum?