Browser-enabled Cross Site Requests

This discussion covers various mechanisms that web sites can use to communicate with each other via a user agent as intermediary. Server-to-server mechanisms are not covered here, nor is server-side proxying of client requests. Also not covered are mechanisms like OAuth. While OAuth involves notifying users about resources accessed from different domains (and thus does include the user agent in the transaction), OAuth goes beyond the scope of this document, which focuses on mechanisms initiated directly within HTML, JavaScript, and CSS by URL dereferencing or browser primitives exposed to web pages.

A few terms should be defined first:

Definition of Terms

Listing of Common Cross-Site Mechanisms

Note that more than one of the cross-site mechanisms below can be used together. When discussing security here, we take a user-centric stance: what does the user know about what could be going on? Can the user's privacy be compromised? The section after this one covers the impact to both Mashup Site and Data Site, and what each must do in order to induce a cross-site request. When we list a potential attack (e.g. XSS or CSRF) we list these as possible under "worst case" usage by Mashup Site or Data Site.

Cross Site Communication Mechanisms
Description of Mechanism Conforming User Agents Security Considerations Other Technical Considerations
Mutually agreed upon iframe and URL loading between sites, typically in sequential order. All
  • Cookies and Auth (private data) can be sent with requests, and user is unaware that such requests are taking place.
  • Data Transferred as part of URI, which gets logged in proxies (easier leakage).
  • Data is transferred 3 times before arriving at Mashup Site.

See Mutual iframe Loading

Mutually agreed upon
location.hash
toggling between iframes (fragment identifiers in URLs), which take place in sequential order.
All (pending investigation)

XSS

  • Cookies and Auth (private data) can be sent with requests, and user is unaware that such requests are taking place
  • Data stream is unprotected; malicious content injection is possible (XSS).
  • Browser may treat hash setting as user navigation, which could get stored in history.
  • Very complicated to implement.
  • Requires polling for data (slow).
  • Messes up navigation history.

See location.hash toggling.

JSON blobs and "script src=" All

XSS; CSRF

  • Cookies and Auth (private data) can be sent with requests, and user is unaware that such requests are taking place
  • Mashup Site must trust that Data Site will not XSS it; Mashup Site must "scrub" code.
  • Data Site may be subject to CSRF attacks, since unless API keys are used, script loading may trigger private data leaks.
  • Unless API keys are used, Data Site doesn't get any information about Mashup Site, thus making safety policies hard to construct.

See Script Loading.

XDomainRequest API IE8 beta
  • Users may not be aware that such transactions taking place, but in general, data from Data Site is public and not private.
  • Can be used to POST random content to servers; the POST method is not pre-flighted.
  • Introduces a new method exposed to window for GET and POST requests that has similar syntax to XMLHttpRequest but has a different method name.

See XDomainRequest.

postMessage for Cross-Window Messaging IE8 beta, Firefox 3, Opera 9.5, Safari (coming soon)
  • Cookies and Auth (private data)can be sent with requests, and user is unaware that such requests are taking place
  • Mashup Site has to open an iframe pointing to Data Site. Data Site can thus engage in misleading content (matching what's on Mashup Site, for example, so that domains are not distinguishable visually).
  • Can only be used for scripts. Cannot be used for XBL, XSLT, SVG for cross-site loads of public data.

See postMessage.

XMLHttpRequest and Access Control TBD; Firefox 3.next
  • Cookies and Auth (private data) can be sent with requests, and user is unaware that such requests are taking place
  • Risk that Data Site will opt in on URLs which serves user-private data without realizing that URL will leak private data. Technical discussions within W3C WG context continue.
  • Reuses the same API as for single-domain invocations. There has been much discussion about whether or not this is confusing for mashup developers.

See XMLHttpRequest and Access Control.

Using Flash and crossdomain.xml

All (with latest version of Flash; or J2SE; or Silverlight)

  • Cookies and Auth (private data) can be sent with requests, and user is unaware that such requests are taking place
  • Risk that Data Site will opt in on URLs which serves user-private data without realizing that URL will leak private data
  • Risks with "*" on policies per domain.
  • Understood risks with file-based policy languages for site access
  • Flash provides further capabilities outside of this discussion's scope.
  • Flash is discussed here because of ubiquity. Flash tyically reuses browser's HTTP stack (limitations of NPAPI).

See Flash.

Further Discussion: What Sites Do For Each Cross-Site Mechanism

This section lists more technical details of the mechanisms mentioned above, and describes what Mashup Site and Data Site do to implement these mechanisms, and thus induce a browser to make cross-site requests between each site.

Description of Cross-Site Mechanisms and Site Roles
Description of Mechansism What Mashup Site Does What Data Site Does
Mutually agreed upon iframe and URL loading between sites, typically in sequential order.

Mashup Site knows about URLs to invoke on Data Site within an iframe. Mashup Site in turn "expects" a URL to be called on its domain after loading iframe of Data Site.

  1. Mashup Site loads an iframe of Data Site, with understood invocation URL of Data Site's resources (example: http://data.site/api/calendar?key=[key]&value=[value].
  2. Mashup Site expects an understood URL of its domain to be called from within Data Site.

Data Site knows about URLs to invoke on Mashup Site especially if invoked from within an iframe by Mashup Site.

  1. Data Site is invoked in an iframe by Mashup Site.
  2. Data Site then invokes a URL on Mashup Site from within the iframe, and sends Cookie and Auth cognizant data in the URL (example: http://mashup.site/data-mashups/[private data blob]
Mutually agreed upon
location.hash
toggling between iframes (fragment identifiers in URLs), which take place in sequential order.

Mashup Site sets "URL fragments" (e.g. http://data.site#frag) on Data Site loaded in iframe. Data Site does the same thing in return.

  1. Mashup Site loads an iframe of Data Site (e.g. http://data.site/api/foo-string
  2. Mashup Site now calls location.hash = "data" on the iframe of Data Site, thus making the URL http://data.site/api/foo-string#data and passing a string to Data Site.
  3. Mashup Site expects to be loaded in an iframe, and expects to have a fragment identifier called on it, thus receiving strings in fragment identifiers.

Data Site "expects" to be loaded in an iframe with a fragment identifier following a given URL. Furthermore, Data Site loads an iframe of Mashup Site and sets fragments on it, thus passing data back to Mashup Site.

  1. Data Site gets passed "data" after Mashup Site (which has invoked Data Site in an iframe) calls location.hash = "data";
  2. Data Site now obtains "data" from Mashup Site, and loads an iframe worth of Mashup Site and calls location.hash="otherData";
JSON blobs and "script src="

Mashup Site loads scripts from Data Site using

<script src="http://data.site/api/scripts/foo.js">

If Mashup Site knows the format such scripts can take (e.g. if Data Site provides well understood JSON blobs) then Mashup Site may simply eval the JSON blobs and obtain data from Data Site. Scripts that Mashup Site loads from Data Site's domain can do most things to properties within Mashup Site's domain exposed at page level access.

Good design suggests that Mashup Site may need to request a key ("API Key") to invoke JSON blobs on Data Site's domain, but this is not necessary.

Data Site's resource (e.g. foo.js) can be loaded from anywhere on the web. Requests for foo.js can be submitted along with Cookies or Auth headers.

Good design suggests that if the contents of foo.js are in any way personal, Data Site should stipulate rules on Mashup Site, such as API keys, etc.

XDomainRequest API

Mashup Site invokes code like:

var x = new XDomainRequest();
x.open("GET", "http://data.site/news/movies");
x.send();

Mashup Site's domain will be sent in the HTTP header request to Data Site, along with a new header ("XDomainRequest: 1") that marks this as a XDomainRequest.

Data Site MUST send "XDomainRequestAllow: 1" header back, thus authorizing the XDomainRequest. If not, response will be discarded by IE8 beta.

Data Site may still receive spurious POST messages to URLs, and may send payloads back.

postMessage for Cross-Window Messaging

Mashup Site loads an iframe from Data Site. Mashup Site invokes a postMessage on Data Site's object.

<iframe src="http://data.site/message/" id="iframe"></iframe>
<form id="form">
<input type="text" id="msg" value="Message to send"/>
<input type="submit"/>
</form>
<script>


window.onload = function(){
var win = document.getElementById("iframe").contentWindow;
document.getElementById("form").onsubmit = function(e){
win.postMessage( document.getElementById("msg").value, "http://data.site/message/");
e.preventDefault();
};
};

Data Site has to provide code that handle the message that Mashup Site posted to one of its objects.

<b>This iframe is located on http://data.site/message/</b>


<div id="test">Send me a message!</div>
<script>
document.addEventListener("message", function(e){

if ( e.origin !== "http://mashup.site" )
return;


document.getElementById("test").textContent =
e.domain + " said: " + e.data;
}, false);
</script>

XMLHttpRequest and Access Control

Mashup Site invokes code like:

var x = new XMLHttpRequest();
x.open("GET", "http://data.site/api/xhr-api-handler");
x.send();

The emerging specification stipulates certain request headers that are sent. In particular, for methods that are not GET, more than one request may be sent (an OPTIONS "preflight" test).

As we determine the headers, this section will list better examples for request headers.

Data Site MUST opt-in to methods other than "GET" (via a preflight test using OPTIONS) and MUST opt-in to sending Cookies and Auth information (pending review within working group).

The onus on Data Site is to send the right headers back.

As we determine the headers, this section will list better examples for response headers.

Using Flash and crossdomain.xml Mashup Site leverages Flash's methods for both HTTP requests for documents as well as sockets. No request headers are sent.

Data Site places crossdomain.xml in a well known location, and it applies for subdirectories.

Data Site may send metapolicy headers back that show locations for crossdomain.xml and what areas are valid locations for crossdomain.xml.