Quick Tip: A Guide to Cross Domain Policy Files

Quick Tip: A Guide to Cross Domain Policy Files

Tutorial Details
  • Program: Flash, Flex
  • Difficulty: Intermediate
  • Estimated Completion Time: 20 mins

Every Flash or Flex developer who has had to access remote resources has come across a crossdomain.xml policy file at some point. This article takes a look at what these policy files are, how they work and how you can create one for yourself.

Example

Let’s take a look at an example of what we’re talking about:

What’s so special about this? Well, the SWF is loading the smiley picture from http://mytestgae.appspot.com/images/smiley.jpg, not from the Activetuts+ domain. Without a cross domain policy file, trying to load the image would trigger a SecurityError.


What is a Cross Domain Policy File?

The security model known as the "same origin" policy, implemented by most modern web browsers, prevents some types of content from being accessed or modified if the file exists on another domain. It’s not a hard and fast rule; HTML pages will happily display images and HTML from pages on other domains. But for JavaScript the same origin policy prevents a document or script loaded from one origin from getting or setting properties of a document from another.

Flash includes a similar security policy which generally prevents a Flash application from accessing data that is hosted on a remote domain. However there are many circumstances where it is not only useful but expected that resources will be accessed remotely. An online photo album would find itself limited if external applications could not download its images. It would also be silly if a web service didn’t allow outside applications to interact with it.

For this reason it’s possible to create an XML file, called crossdomain.xml, that specifies how data on a domain can be accessed by a Flash application hosted on a remote domain. For the most part these policy files are quite simple, but there are a few details that it is useful to be aware of.

If you are hosting content that you want to be accessed by external Flash applications, you will need to create a crossdomain.xml file. Let’s start by taking a look at a basic example.


Step 1: A Basic crossdomain.xml File

Here is a very simple crossdomain.xml file. When this file is hosted on the root of your domain it permits external Flash applications access to all the resources on your domain.

<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*" />
</cross-domain-policy>

The policy file contains a single <cross-domain-policy> tag. Inside this you can have zero or more <allow-access-from> tags. Each <allow-access-from> tag can be used to define a domain or IP address from which a Flash application can access the local resources. The attribute domain="*" specifies that all domains have access. This is thanks to the asterisk wildcard, which is used here to match all domains and IP addresses.

For most situations this "allow all" policy file is sufficient. It grants Flash applications access to all pubic resources, while any security you have in place (like password protected pages) will still prevent Flash applications from accessing sensitive data.

(Note that you cannot put a crossdomain.xml file on your domain that will allow SWFs also on your domain to access remote files on another domain!)


Step 2: Specified Domains

If you do not want to allow global access to your public resources, the domain attribute in the <allow-access-from> tag can be used to grant access to specific domains.

You can specify a domain in its entirety. The example below will give access to Flash applications hosted in the www.example.com domain.

<allow-access-from domain="www.example.com" />

You can use the asterisk wildcard to match those domains that end with the given suffix. Here we grant access to Flash applications on the domains example.com, www.example.com, whatever.example.com etc.

<allow-access-from domain="*.example.com" />

Step 3: Specified IP Addresses

You can specify access by IP address just as you can grant access to Flash applications hosted on specified domains. The same tag and attributes are used, except in this case you use an IP address:

<allow-access-from domain="123.456.789.123" />

Step 4: Working with HTTPS

By default a Flash application hosted on an HTTPS server can only access resources on remote HTTPS servers. But given the overhead that HTTPS can add to a server you may not want to use it. In this case setting the secure attribute to false will allow a Flash application on an HTTPS server to access data from an HTTP server.

<allow-access-from domain="*" secure="false"/> 

Step 5: Remote Flash Applications

So what if you don’t want remote Flash applications accessing your data? You can either create a crossdomain.xml file that does not include any <allow-access-from> tags:

<?xml version="1.0"?>
<cross-domain-policy>
</cross-domain-policy>

Or you can simply not have a crossdomain.xml file at all.


Step 6: Granular Control of Subdirectories

A cross domain policy file will control access to the directory it resides in, and all the subdirectories beneath it. This is how placing a "allow all" policy file at your domain root allows access to your entire domain. But there may be situations where you want to only allow access to a certain subdirectory.

With the latest versions of the Flash Player this requires two XML files. First you need to place a crossdomain.xml file in the root of your domain that allows Flash to process additional cross domain policy files within the subdirectories. This is done with the <site-control> tag. In the example below we set the permitted-cross-domain-policies attribute to all, which means that the cross domain policy files that may exist in the subdirectories will be processed. This behavior is a change in Flash Player 9 Update 3 and up. Previously policy files in subdirectories were processed by default without having to set the permitted-cross-domain-policies attribute.

Note that we have not added any <allow-access-from> tags, which means in the absence of an additional crossdomain.xml files in the subdirectories, remote Flash applications will not have access to the resources on this server.

You can find out more about the meta policy options in this article.

<?xml version="1.0"?>
<cross-domain-policy>
<site-control permitted-cross-domain-policies="all"/>
</cross-domain-policy>

Next, you place a crossdomain.xml file in the subdirectory you wish to control.

To see an example of this in action check out this file. This policy file, in the root of the http://mytestgae.appspot.com/ domain, uses the <site-control> tag to delegate control to any crossdomain.xml files that may exist in the subdirectories. Then this policy file in the /images/ subdirectory grants full access to the directory and any subdirectory beneath it. So a remote Flash application could access the smiley face image in the images directory like so:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
	xmlns:mx="http://www.adobe.com/2006/mxml"
	layout="absolute"
	width="550"
	height="400"
	applicationComplete="onAppComplete()">
	<mx:Image id="image" scaleContent="true" horizontalCenter="0" verticalCenter="0"/>
	<mx:Script>
		<![CDATA[
			private function onAppComplete():void
			{
				Security.loadPolicyFile("http://mytestgae.appspot.com/images/crossdomain.xml");
				
				var loaderContext:LoaderContext = new LoaderContext();
				loaderContext.checkPolicyFile = true;
				
				var loader:Loader = new Loader();
				loader.contentLoaderInfo.addEventListener(
					Event.COMPLETE,
					function(event:Event):void
					{
						image.source = event.currentTarget.content;
					}
				);
				loader.load(new URLRequest(encodeURI("http://mytestgae.appspot.com/images/smiley.jpg")), loaderContext);
			}
		]]>
	</mx:Script>
</mx:Application>

However, access to the smiley face image in the /images-restricted/ directory is not permitted because there is no crossdomain.xml file in the images-restricted directory to override the (lack of) access granted by the crossdomain.xml file in the root of the domain. Running the code below will result in an exception being thrown:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
	xmlns:mx="http://www.adobe.com/2006/mxml"
	layout="absolute"
	width="550"
	height="400"
	applicationComplete="onAppComplete()">
	<mx:Image id="image" scaleContent="true" horizontalCenter="0" verticalCenter="0"/>
	<mx:Script>
		<![CDATA[
			private function onAppComplete():void
			{
				var loaderContext:LoaderContext = new LoaderContext();
				loaderContext.checkPolicyFile = true;
				
				var loader:Loader = new Loader();
				loader.contentLoaderInfo.addEventListener(
					Event.COMPLETE,
					function(event:Event):void
					{
						image.source = event.currentTarget.content;
					}
				);
				loader.load(new URLRequest(encodeURI("http://mytestgae.appspot.com/images-restricted/smiley.jpg")), loaderContext);
			}
		]]>
	</mx:Script>
</mx:Application>

The exception reads:
SecurityError: Error #2123: Security sandbox violation: LoaderInfo.content: file:///D|/CrossDomain.swf cannot access http://mytestgae.appspot.com/images-restricted/smiley.jpg. No policy files granted access.
at flash.display::LoaderInfo/get content()
at MethodInfo-635()


Step 7: Cross Domain Policy vs. Firewall

So from the above information it looks like cross domain policy files can be used to effectively restrict access to Flash applications not hosted on your own domain. While that is true, you should not rely on a cross domain policy file to restrict access to sensitive information. While Flash may respect a crossdomain.xml policy file, other platforms like PHP won’t. Do a search for PHP Flash Proxy to see what I mean. By using a proxy it’s possible to get access to any publicly available data regardless of the existence of cross domain policy files. And you don’t even have to pay for a PHP server – as I will demonstrate in a future article, Google App Engine can be used as a proxy with no up front costs.

The bottom line is that cross domain policy files provide a way to selectively grant access to local resources by remote Flash applications, but only if everyone plays by the rules. If you want to ensure that your private data stays private, there is no substitute for a firewall.


Conclusion

Dealing with cross domain policy files doesn’t need to be complicated. Once you understand the basics of how they work it is quite easy to grant or restrict access to your data by remote Flash applications. Just be aware that they are not as secure as they might initially seem.

I hope you liked this Quick Tip, thanks for reading!

Tags: Tips
  • Pingback: uberVU - social comments

  • http://www.webguide4u.com WebGuide4U

    thanks for the. Will be looking for this for a long time finally get it

  • http://ilopezdeaudikana.com mutiu

    thanks for this very neat explanation….

  • http://dingoeatingfuzz.net MIchael Lange

    Nice tutorial. Now if only big websites would make a cross-domain policy file (I’m looking at you, Flickr). The work around there is to make a server-side proxy script to load in the image instead of Flash. Of course, this opens up another bag full of security issues.

    One neat trick, if you can’t get a cross-domain policy file on the required domain is load the image with a Loader object, much like you are, but instead of casting the content to a new bitmap/display object, just add the Loader object to the display list. The Loader object naturally renders its content object. The drawback to this is bitmap objects don’t naturally have smoothing turned on :\

    Once I get around to building my website, I’m sure I will be referencing this tutorial again.

  • Pingback: Quick Tip: A Guide to Cross Domain Policy Files | Activetuts+ Zero Me

  • Murray

    Thanks for this resource. I’m having a nightmare trying to embed a youtube video into a website I’m building. Even with the basic xml file in the root of every page, whenever I preview the page from Dreaweaver, it pops up with the adobe flash secuirty warning!! Will this happen once the site is published or will visiotrs still see the popup? Any suggestions on killing it would be very, very helpful!

  • Pingback: Quick Tip: Using Google App Engine as a Proxy Server | techglow.co.cc

  • Pingback: Quick Tip: Using Google App Engine as a Proxy Server - GFX Me

  • Willie Smoot

    “For most situations this “allow all” policy file is sufficient. It grants Flash applications access to all pubic resources, while any security you have in place (like password protected pages) will still prevent Flash applications from accessing sensitive data.”

    This is incredibly bad advice. The point of the crossdomain policy isn’t to prevent scripts from accessing your site, it’s to prevent sites from forcing your users’ web browsers to access your site. In effect, you are making every web site that follows this recommendation vulnerable to CSRF and Flash-based XSS attacks.

    For example, if an administrator is logged into your password protected pages, and views a page on my server, my server can load up a flash object that forces him to make any requests I want- as an authenticated user. It can also read the results, giving him the ability to steal information out of that password-protected portion of the site.

  • http://www.arenddeboer.com SoonSpoon

    Nice article. Even though I understand the need for a strict security model it also makes building web applications harder. Most of the time, you cannot place a crossdomain-policy file because you do not control//own the remote server. So the only way is setting up a proxy to relay requests for flash which opens up a host of other security concerns let alone the additional bandwidth costs.

  • http://www.darnkitty.com/ Matt

    Hi! Just wanted to say, my crossdomain.xml files in my subdomains just weren’t working, and I probably wouldn’t have got them working correctly if it weren’t or this tutorial. Thanks so much.

    • http://michaeljameswilliams.com/ Michael James Williams

      That’s great to hear, Matt! Thanks for letting us know :)

  • abiel

    Trying to access http://mytestgae.appspot.com/images-restricted/smiley.jpg, i was thinking it would not even fetch it from the server. But what I see is it fetches it to the browser but it doesn’t display it. I verified this in firbug. The resources is downloaded from server.
    When I run the code I got the exception that you mentioned and with two options “dismiss all” and “continue” I pressed continue, and there in firebug i see the image, but it’s not displayed. Is this the way it is supposed to work?

  • aaron

    flex 3 no problem. in flash builder 4.5 return error: This may be worked around by calling Security.allowDomain