System Applications WG: Cross Origin XHR

From W3C Wiki

Problem statement

In current runtime proposal, local resources in a packaged app have "app://" based origin, and every XHR request to http/https url will initiate a cross origin XHR. Since most of the servers are not aware of "app://" origin and even not CORS-enabled, the XHR will simply fail due to same-origin policy.

Existing approaches

Firefox OS provides a modified XHR API to relax same-origin restrictions [1], and Chrome allows Extensions to specify origin white-listing to by-pass CORS checking [2].

(new XMLHttpRequest({mozSystem:true});) 

[WARP] [3] is the widget-land solution.

Analysis

In general, it'll be better to reuse existing XHR without modification, and also better to provide the cross-origin XHR functionality to as many apps as possible (i.e., not only restricted to "certified" apps).

Which type of app does this affect?

  • For websites, there is no issue: cross-origin XHR is supported so long as the server supports CORS and the client doesn't have a content security policy preventing it.
  • For 'certified' packaged apps, it also seems less of an issue: cross-origin XHR could probably be permitted for any app, and will be for any with access to raw sockets. These are native replacements and so it seems reasonable to allow cross-origin XHR. An optional whitelist of trusted origins may be sensible, though.
  • For 'privileged' or 'web' apps, it is less clear what to do. The use cases are (I assume) - accessing content from publicly available websites (e.g., obtaining news / status reports), accessing data from the app developer's own domain (which may be different from the app's origin if it is packaged) and creating mash-up applications that may make use of user credentials. For these apps, I am not aware of any use cases where completely unrestricted XHR (a '*' policy) is needed, as 'web' apps wont have access to the raw socket API.

So far, we have only discussed packaged rather than hosted apps.

What is the risk of allowing cross-origin XHR?

We have let to talk about the risk of permitting cross-origin XHR. The advantages of cross-origin XHR are pretty obvious, the main threats are:

  • Cross-domain attacks, primarily CSRF (the confused deputy problem). An app could be used to make authenticated cross-origin requests to another domain and therefore access web-based user data or services. The likelihood and impact of this attack depends on whether cookies will be set on cross-origin XHR (e.g. whether 'omit credentials' is used).
  • Cross-site scripting is a problem if XHR is used to load scripts from remote origins. Is this a common use case?
  • Privacy violation and local network scanning: cross-domain XHR can be used to scan local networks, and to use timing information to estimate the user's favourite domains. There are other attacks around this area too.
  • DoS attacks: a popular malicious app could be updated by its developer to make many requests to the victim's website, thus compromising availability. This is less of a threat as this vector is available through other means (image tags), and should be relatively easy to spot and recover from.

The likelihood of misuse of cross-domain XHR depends (in my opinion) partly on the ease at which a webpage can be 'upgraded' to become a 'privileged app'. If it is easy and commonly done, then this will be the way that many websites get around the same-origin policy (imagine instructions such as "click 'install' to enable full functionality"). We must assume that this will happen and, therefore, that significant numbers of malicious apps will be installed at the 'privileged' level. The threats are therefore not to be ignored, unless additional constraints are placed on installation.

What are the outstanding issues and considerations?

  • Least privilege security is desirable to allow apps to restrict the origins with which they are able to interact. This prevents apps from being modified at runtime to access malicious content from other servers.
  • From a developer perspective, apps designed primarily for the web will likely be developed with browser-like security assumptions. Developers may assume strong restrictions by default, and this specification shouldn't disappoint.
  • CORS may or may not be supported by the remote server and there is some concern that it is not a useful mechanism right now. If CORS were to be followed by privileged web apps, it might force app developers to make apps 'certified' when they don't need to be, which makes them more privileged and therefore potentially more harmful. This is to be discouraged. Furthermore, the origin header set by the runtime of a web app is currently unclear.
  • CORS should either be enabled or not - having a client-side way of turning CORS checking on or off seems like a bad idea, as CORS is supposed to be a server-defined policy, even if it is client-enforced.
  • User interaction and consent is not likely to be a useful part of any solution. Any user consent that is required can be supported by the application and remote origin if necessary.

What are the potential implementation options?

  1. Application manifests could support a field defining permitted domains that apps may access through cross-origin XHR. This is the most straightforward approach, although it does raise questions about whether this should apply to websockets as well, whether it takes precedence over any CSP rules or not, and so on. It also presumably requires CORS to be ignored (or the semantics to be altered).
  2. Applications could use a CSP connect-src string also defined in the manifest to whitelist permitted domains. This would need to default to 'self' unless set, and disallow '*' for privileged (not certified) apps. This is equivalent to option (1) but also covers websockets. The only advantage is that it doesn't introduce a new mechanism (although it changes the default CSP rules) and developers have exactly one way to implement an XHR whitelist for their app. It also presumably requires CORS to be ignored (or altered to be more permissive by default).
  3. Follow CORS and introduce no *new* way of permitting cross-origin requests.

Example of (1) as proposed by Jonas:

permissions: {
 systemXHR: {
   description: "...",
   servers: ["https://www.foo.com", "https://www.bar.com"]
 }
}

References

[1] https://groups.google.com/forum/#!topic/mozilla.dev.gaia/sc-G5prl7D8

[2] https://developer.chrome.com/extensions/xhr.html

[3] http://www.w3.org/TR/widgets-access/