Beyond the Code

Just another Blog.mozilla.com site

Jetpack tests unhidden on the try servers!

Finally the tests of the Add-on SDK will be unhidden on try servers! It’s good for us since we don’t have to check all the time which patch broke our tests, and it’s good for everyone, since we will have more tests. But it also comes with some pain since, everyone will have to learn a bit about our tests, and since at the moment landing anything in the Add-on SDK part of m-c is not straight forward (see below). I expect some annoyance, and I do my best to help to ease some of it, and make this transition period as smooth as it can be. Here is a start (not much for now, but I plan to add more stuff to this and extend it to a FAQ maybe)

Running the tests:

Start here: Our awesome test guide.
TL;DR : if a simple ./mach jetpack-tests is not enough try this:
If you want to specify a single test to run you have to use cfx. For cfx you have to specify the firefox binary manually you want to run the test against. Here is a typical use case:
1, go the the addon-sdk/source dir
2. run: bin/cfx testall –binary ../../obj/dist/bin/firefox.exe –filter test_dom
–binary [path to your firefox executable you want to test]
–filter [if a tests filename does not contain this string it will not be run]

All of a sudden timeout!

There are some timers set up in the test runner that kills the process after a while, which can make debugging frustrating. To optionally turn them off I just filed a bug.

Let’s change some tests!

So you want to change something in the SDK code. Since the SDK is a GitHub based project and has got into the Mozilla central only recently, the current process what we have is not the best. The development of the SDK is still on GitHub, and we merge in the changes every now and then into the Mozilla central repository. Possibly/likely overwriting your changes on it, if we are not aware of them. So if it’s something tiny, like a minor change in some tests, just let us know, or file a bug about it. If you want to make some real contribution to the SDK or land bigger changes you should do that on GitHub. WARNING: Pushing your changes to m-c without warning us will likely
result in your changes being overwritten.

WAT?

So you have questions. Feel free to hit us up on IRC in the #jetpack room. Gozala is the project leader, but you can also ask Ochameau, ZER0, wbamberg, Mossop, KWierso, canuckistani, erikvold, jsantell.
And there is Eddy (ejpbruel) and me (gabor) who are the C++ developers of the team and working on the platform code mainly but always happy to help out others (or die trying), you can try us too.

Security wrappers and Add-on development

Importance of security

One of the most important benefits of developing an add-on instead of a regular website is the extra privileges that you can get. What most people don’t consider is that power always comes with responsibility. It’s difficult to decide how much freedom an add-on developer should have. I think the best answer: is as much he needs. No more, no less… If life were only that simple… On the one hand we want add-on development to be simple and natural for a web developer without continuously worrying about questions like ‘is it safe to do this and that?’. On the other hand we want to give them full access to APIs that should only be used by thoroughly reviewed and tested system code… It would not be fair to put all the responsibility on add-on developers and add-on reviewers. If add-ons can be a security threat for the end user, that will harm both the reputation of the browser and the usage of add-ons in general. So the general principle that we’re trying to follow here is: only give access to things that you really need. And if you want to do some wicked things, unleashing the full capacity that the Gecko environment has to offer, then yes, you need to understand what you’re doing and can expect a longer review process…
The usual way add-on developers discover the security layer is by bumping into some security limitation that might be a totally confusing experience in some cases. I’m writing this blog to collect a few typical cases where this can occur, and to give you a brief description of the security layer in general. I think this is important, because knowing at least a little about it can help you understand what can it do for you. Not to mention that it can be extremely frustrating when you bump into an unexpected security limitation and don’t even have a clue what is going on.
I put security scenarios in three big categories for now.

  • Regular web security (XSS, same origin, cross origin, etc.)
  • Preventing leaking out system (chrome) privileges
  • Accessing untrusted DOM safely from trusted code

I don’t want to discuss the first topic this time. It’s something every browser have in common and most web developers have a fairly good understanding of it, and the spec is available for everyone.
Chrome (or system) privilage: In Gecko some javascript code runs without any restriction and can have access the chrome API that is unavailable for regular home pages. Either system code, or some addons that went through a review process. It can also have access to any origin. The worst possible thing that can happen security wise is leaking out chrome privilege to web content. It has to be prevented at all cost. So exposing object from chrome scope to content is rarely a good idea. Sometimes it’s necessary, and there is a security layer to prevent leaking, but still, any bug or mistake here can cause an immediate security critical bug. First the content-script of the Add-on SDK had system privileges. Since it’s a code that meant to interact with content, it turned out not to be a good idea. It is simply to ‘close’ to content. Right now it has the same privileges as the site it can interact with. This however turned out to be too much of a restriction in some cases. Currently a new version is being released where you can specify an array of origins for content-script it will gain same origin access to. And in the near future I hope I can add another feature that will enable wild cards in those origins.

And finally, when we want to manipulate the DOM of the content, or simply want to interact with it, there is nothing that would guarantee us that the the DOM has not been mutated by content at the time. We don’t want some untrusted site to trick our add-on code, or the other way around, our add-on should not have any unexpected side effect on the site. For example the content could have replaced getElementById with some custom magic, that returns something else than we expected, or does some crazy things. Or we might use a global variable that is used by the site as well and we get in conflict with it. We need a mechanism to see through all these ‘mutations’ and being able to reach the original DOM functionality we know from the specs.

Security wrappers

Making every operation ask the security layer whether it’s allowed or not would be way too slow. So instead, as in the Object-capability model, the idea is that getting a direct reference to an object means simply that permission is granted. Objects from the scope of a different global will never get direct
references to each other. Instead we create a filtering wrapper for the object from the other
scope and reference that. Let’s see what that looks like.
Cross Compartment Wrappers

Each global object and every object in their scope ends up in the same memory block. These separated blocks of memory are called compartments. Different globals are always in different compartments. On the picture circles are JS objects, rectangles are cross compartment wrappers, filled circles are the global objects in the given compartment. It is really simple: whenever an object from compartment A gets a reference to an object from compartment B, xpconnect kicks in, creates a wrapper, and references that instead. Now whenever you try to do an operation on the given referenced object, the wrapper decides what to do. Basically there are two kind of wrapper behaviors. Filter and Xray. A particular wrapper can be both filtering and have xray behavior in the same time.

Filtering wrappers

The first one is really simple, it decides whether an action should be allowed or denied. For example the cross origin behavior is implemented with a filtering wrapper. Another example you might come across (if you plan to implement a Jetpack module at some point…) is that if you try to expose an object from chrome to content, by default none of the exposed object’s properties will be accessible to the content. If you want to expose some properties of your object (and unless it’s a function, you probably do…) you need to specify them with the help of the __exposedProps__ property on the chrome side. It’s easy to see that this is just another filtering wrapper.

Xray wrappers

There is a problem that cannot be solved with a filtering type of wrapper. When system code accesses the DOM of an untrusted site, because of the flexible nature of JavaScript, nothing guarantees that methods and properties are not mutated by the site. It’s not just a security problem, that the site can trick system code: system privilege will not be ‘leaked’ in this way. So even if system code calls content.document.getElementById(‘something’) and the site has replaced getElementById with some custom function to do something evil, that function will NOT be called with system privileges. So in a way we’re safe… But still, it would be nice if I could call the original getElementById reliably and get the expected result. Also we don’t want to cause any side effect on the site accidentally in this way.
Xray wrapper is designed to solve this problem. But to understand how it is possible, we need to look under the hood for a second to see how binding is implemented between a C++ instance and a JavaScript object. This is a very complex part of XPConnect: there are several ways to do it, there is a lot of optimization, currently a new DOM binding is being introduced… so I will not get too deep into this topic for now. From our perspective it does not matter. What is important is that there is a native layer here. By native I mean that it is implemented in C++. (Actually it might be implemented in JavaScript and then wrapped in a special wrapper to fake a native object, but let’s not go there for now…)
The good news that while JavaScript is very flexible when it comes to mutating instances at runtime, C++ is not. No one can change the vtable of a C++ instance during runtime, so we can safely assume that if we call a method on a C++ instance, it will do what we expect it to do. By now you probably guessed that what xray wrapper does: it sees through the JavaScript reflector object and calls the native method. But to make it less foggy, let me explain how this really works in a nutshell.
So we have an instance in C++, for example a WebSocket. It has C++ methods. To bind them to the JavaScript API we have a reflector class called XPCWrappedNative, that wraps the native instance and propagates the JavaScript calls to this instance. There is also a JavaScript object called the holder, which is the WebSocket object we see from JavaScript usually. The holder will either propagate the operation to the XPCWrappedNative, or if the operation is a mutation, this is the layer that will store it. So when someone adds a new property, it will be added to this holder (we call these expando properties). If someone overwrites a method, an expando property will be created on the holder which will shadow the native one.
What xray wrappers do is ignore this holder object with all its mutations and call the XPCWrappedNative directly.
Please note that this is an oversimplified version and the actual implementation is a lot more complex, but my goal is only to give some high level picture of what is going on, and more detail would just defeat that purpose.
Xray behavior

Jetpack content-scripts

Let me start with a scary looking picture I found in the Add-on SDK docs:

multiple-workers

I have to note first of all, that Content process and Add-on process are actually the same process, since the whole Firefox engine is pretty much single processed. At some point that was about to change, but right now it seems like it will not (at least not anytime soon). But the two sides in fact act like two separate processes from the add-on developer’s perspective: content scripts and workers communicate via messages, and that serves security purposes (and maybe in the future they will be separate processes, who knows?).
What’s important for us now is: where are the different scopes, or: where are the compartment boundaries? And what kind of privileges does each have, and what ‘side effects’ can we run into because of them? In the next section I collected a couple of examples, but let’s get the big picture first.
Everything on the right side lives in a chrome compartment. Actually each module has its own global, and all of them have system principal rights. For now: one global on the right side, with system level of privileges: that is, ‘it has access to everything’. On the left side each web page has its own global. In fact each iframe within the web pages has its own globals… Apart from that there is our content script that has the same origin by default as the web page it is ‘injected’ into. It has its own global and scope. Actually as I mentioned, content scripts in the future will have optionally slightly higher privileges than web sites.
Anyway, what is important now is to understand that each content script has its own global, and that by default it is using xray! The xray is to make your life better, but sometimes it can get in your way. You can kind of turn it off when you have to (although I don’t encourage anyone to do it, in some special cases I can see the use of it). The other important thing to note is that expandos of the content-script are invisible from the web-page, and the other way around too. This is very important, since if that were not the case, content scripts from different add-ons would get in conflict with each other very easily.
(If someone wondered, iframes with same origin can see each others expandos, otherwise the specs were broken, but I will not get into implementation details here how that problem is solved…)

Examples

When content scripts interact with web content, there are a few cases where you should be aware of the existence of these wrappers to understand what is going on. I will try to explain in each cases what is happening and why, and also where you need to work around unexpected behavior.

Expandos

As I mentioned earlier, web content and content scripts have their own separate globals and compartments for their objects. Since they have different globals, and their objects live in different compartments, they can interact with each others’ objects only via wrappers. So when you write something like ‘document’ or ‘window’ inside a content script, you can be sure you are working with a wrapper. Expando properties cannot be seen through this barrier, and global variables are actually expandos on the global… So if the web content sets a global variable or puts a new property on a DOM node for example, by default it cannot be seen from the content script.

Content

// Global variables
var div1 = document.getElementById("div1");
// Expando properties
div1.blah = "WAT?";

To make these expandos visible, there is a way to unwrap xray wrappers by accessing the wrappedJSObject property. Or in case of window there is a special unsafeWindow object for this purpose.

Content-script

// unsafeWindow:
unsafeWindow.div1;
// unwrapping
var div1 = document.getElementById("div1");
div1.wrappedJSObject.blah;

I don’t encourage anyone doing this trick in general. It can lead to all kinds of nasty surprises. But for example if we are the developer of an actual website, and just want to implement an add-on that is extending the capabilities of that particular site only… Why not?

Xray

In the next example I want to demonstrate what the xray behavior means in practice. Again, if you for some reason want to avoid this behavior you can by unwrapping…

Content

var div1 = document.getElementById("div1");
var origAppendChild = div1.appendChild.bind(div1);
// let's overwrite a well known DOM method on a node:
div1.appendChild = function(child) {
  // the modified version
  // first calls the original version
  origAppendChild(child);
 
  // then adds an extra text node to the document
  origAppendChild(
      document.createTextNode(
          "An additional text node."));
}
// this call will call the new version obviously
// and result an addition text node appended to 
// the document after the one we pass in as an argument.
div1.appendChild(
    document.createTextNode(
        "Child inserted from the content"));

‘document’ in the content script is an xray wrapper for the content’s document. Xray wrappers work in a transitive way: any object its properties or methods return is an xray wrapper too. If that logic is hard to follow then you can look at any node and ask: where does this node belong to? If it’s a node from the document of the content, and you are writing content script code, you can safely assume it’s a wrapper. Content scripts do not have their own document, only the document of the content, so the answer is really simple usually

Content-script

// div1 is an xray wrapper here since the node is from the document of the content
var div1 = document.getElementById("div1");
 
// because of the xray behavior this call will ignore the modified version of appendChild
// and will call the original one, so no extra text node will be appended, only the one we
// pass in as an argument
div1.appendChild(
    document.createTextNode(
        "Child appended from content.js"));

Events and callbacks

As an exercise here are three ways to add an image with an onclick listener to the content from a content script. And finally a 4th version that just injects the whole thing as an HTML string using innerHTML.

Content-script

function myFunction(){
    alert("WAT?");
}
var img = document.createElement('img');
img.src = "wat.jpeg";
 
// three alternative ways to add the event
// (obviously using only one of these at a time)
// version 1:
img.setAttribute("onclick", "myFunction()");
 
// version 2:
img.onclick = myFunction;
 
// version 3:
img.addEventListener("click", myFunction, false);
 
// finally adding the img to the document
document.getElementById("div1").appendChild(img);
 
// version 4: instead of using createElement/appendChild
// using innerHTML:
document.body.innerHTML = '<img onclick="myMethod()" src="wat.jpeg" />'

And here comes the solution and explanation. Version one will not work. Why? Because the event will be executed in the scope of the content. ‘document.createElement’ will create the element in the scope of the document which is the content. Now in the scope of the content there is simply no function with the name ‘myFunction’. In case you wonder if there is one with the same name accidentally, it will be called! Version 2 will work. There we pass in the ‘myFunction’ as an object not just its name, so it will be called (via a wrapper since from the scope of the content that object is only accessible via a wrapper). Version 3 will work just fine too. The fourth version will not work again for the same reason as for the first version.

“can’t access dead object”

Finally I wanted to take a look at this cute exception. You might bump into it in the future and there is some info out there about it already, but since at this point you know a bit about cross compartment wrappers already, it’s quite simple to fully understand what’s going on here. From GC perspective, sometimes it’s really hard to unload compartments, because of all the cross compartment references. So you close a tab for example but your add-on hooked in some listener to it’s window, or you disable an add-on, but some site holds a references to one of it’s object for some reason, and the GC will decide to leave all those object in that compartment alone in the end… And the user just experiences that the browser needs all the memory on the word and then some more (OK I’m exaggerating a bit).
In both cases (add-on gets disabled, window gets closed) what happens is that the compartment of the window or add-on, with all the objects it contains, is just getting nuked, and all the cross compartment wrappers of other compartments that points to some object from it is getting replaced by a stub wrapper, that basically just throws whatever you’re trying to do with it. For example: your add-on sets up an onclick listener on an image from the content, and the callback function is defined in the content-script. Then the user disables your add-on, and click the button. At this point your add-on and all it’s object included the callback function is just gone. The content had access to the callback function via a wrapper (since it’s a different scope/compartment), and that wrapper is replaced by this stub wrapper. So when the callback is tried to be called by content, it will try to access this stub and the “can’t access dead object” exception will be thrown. True story.
Well, this was it for now, I hope you enjoyed it, and I really hope it helps some people out there. If you have any questions, feel free to ping me any time on irc, or if you have some wrapper related bug to report please don’t hesitate to file a bug.

Security wrappers, part 1: Basics

When I joined the Jetpack team half a year ago, the first bugs I started to work on were related to security wrappers and reflectors. I have to admit that I have never ever in my life had a more challenging start at a new company than this. Soon I discovered that xpconnect is about as popular a part of the Mozilla platform as IE6 in the web developer community. Yes it is messy. And yes it is complex. But let’s face it, it is one of the most important core parts of the platform.

I strongly believe that many new platform hackers will find this article useful. But not just c++ hackers should be interested in this topic. Security comes with restrictions. And many folks out there are confused when they bump into an unexpected behavior in javascript that is caused by some mysterious wrappers.  In the meanwhile I know from experience how difficult is to get any information about them, so Eddy Bruel and I visited Blake Kaplan in Paris to learn more about wrappers to spread the word :)

This is going to be a long journey. Instead of writing a gigantic article that covers _everything_, I’m going to write shorter blogs about different topics around xpconnect. So let’s start with the basics. There are 2 articles I know of on wrappers and I think they are a good start: https://developer.mozilla.org/en/XPConnect_wrappers and https://developer.mozilla.org/en/XPConnect_security_membranes. There is only one problem with them: they are a bit outdated. Ok there is something else too… just by reading these articles don’t even dream about finding it easy to find your way in the code, or to debug it… But I’ll get back to that on another post. I hope someone will find my additions useful.

Let’s start with the distinction of wrappers and reflectors. The term reflector is not really documented yet anywhere. But since the term wrapper was used for two completely different concepts, to avoid confusion this new term was invented and used ‘in house’. So reflectors are responsible for the transition between javascript and c++. So XPCWrappedNative is wrapping a native object and expose it to javascript, and XPCWrappedJS is responsible for the other direction, wrapping a javascript object and let native C++ code operate on it.

Before we talk about security wrappers, let’s talk about principals for a second. Principals are our security tokens, determining what a script can or cannot do. A typical principal is comprised of an URL scheme, host, and port. So if an object wants to do some operation on another object from a different script, the principals of the two scripts will be compared to allow or deny the operation. If the script of our site wants to have access to some object of an iframe, we check if the principal of the site and iframe are same origin, and if so, we can apply the same origin policy, otherwise we have to be much more restrictive.

There are two special principals as well. The system principal that has same origin rights to any script with any other principal, and even can access system level API as well. Scripts with system principal are referred to as chrome code, scripts with regular principal are content code. So chrome code is usually code, written by mozillians, or some addon developers, operating often at browser level (UI for example), or even system level (managing threads, monitoring memory usage, etc). The other one is the nullprincipal, that has minimal privileges, so it never has same origin policy, not even with other scripts that have nullprincipal as well.

Security wrappers (from here on I will refer to them simply as wrappers) are our shield against all the “evil” sites out there, limiting what we can do with the wrapped objects. This first article will be about the security wrappers. So referring back to the previous example, a security wrapper will contain the logic (code), that actually check the two principals against each other and throw an error if the operation should be denied.

The idea of security wrappers in general is that we don’t want objects have direct, uncontrolled access cross origin, and even less between chrome and content scripts.

Let’s speak a few word about how is this all implemented. So objects from the same origin live in their own separated chunk of memory, called the compartment. Each of these compartments have their own principal (and own global object as well). So in general we don’t let an object have direct access to another object from a different compartment. Instead, when an object is exposed to another script, we create a proxy object in the compartment that belongs to that other script.

A proxy is an object that delegates the operations to the object in the original compartment it was created for. A security wrapper is simply a filtering proxy, with some policy. The policy tells in a certain case whether the operation should be allowed or denied. Before delegating the requested operation the proxy first checks if according to its policy it should allow it or if not it throws an exception or fails silently.

For example: my script has a reference to the document element of an iframe, and I want to get its children. What will happen under the hood is that in my script’s compartment there will be a filtering proxy object created, and when I access a property on it to fetch the children, assuming its policy allows it, the proxy will delegate the call to the underlying object in the other compartment.

Wrappers between chrome and content

ChromeObjectWrapper (COW), XrayWrapper (XPCNativeWrapper) and XPCSafeJSObjectWrapper (SJOW)

If we would let any site access some system level API only chrome code should have access to, this would be a major security problem. Even if some unsafe code is able change something on the base classes of a system compartment (String, Object, etc.) there could also be dangerous side effects. So when some object has to be exported from chrome to web content the security wrapper we create is called the ChromeObjectWrapper, which is the filtering wrapper in the content compartment.

The other side of the story is when our chrome code is accessing objects from some content code, typically DOM elements and other WrappedNatives. In this case we expect certain behavior from the object, but javascript can be sometimes too flexible. If untrusted sites were capable of overwriting methods on DOM elements, it could trick us to call their possible evil code from chrome context. On the other side users of course want to be able to overwrite properties and methods on the DOM elements.

This is where XrayWrapper enters the picture. XrayWrapper detects the native object on the content side, ignores every javascript based modification from content side on it (overwritten properties, getters, etc.), and calls right the native implementation of the method. So it comes handy that those DOM elements are implemented in C++, and when it is exposed to javascript, it is wrapped in a JSObject, and all the modifications and extensions happen on this JSObject, so we can just simply ignore those. Even in cases where, on content side, the getter of the window.location is overwritten, when chrome code tries to access the property via an XrayWrapper it will use the original native implementation of the location getter. So here the “policy” of the security wrapper is quite special, and not really principal driven. In fact, XrayWrapper is a very special security wrapper, even its implementation is separated from the rest of the security wrappers.

Note: XrayWrapper used to be called XPCNativeWrapper, and in some places of the code (constructor) and in most of the docs they are still called like that. This is confusing and it makes it even worse that WrappedNative is a completely different thing with very similar name, but hey, I warned you upfront that it gets a bit messy sometimes…

Some more magic: there is a case when XrayWrappers are too restrictive and we want to have access to the underlying object (on our own responsibility) without these limitation,  for example, a debugger wants to access some global variables of the debugged code. Here we can use the so called wrappedJSObject property on the wrapper which will unwrap the underlying object and use a completely transparent wrapper. At this point I hope I don’t have to explain why is this unsafe, but in some cases it can be useful. It basically goes from very secure to “watch your steps” mode, as in: chrome has to be very careful about the assumptions it makes about the functions it calls, since they can now do anything and return any sort of value. So simply calling a function or getting a property will not give chrome privileges away. So it cannot happen that we call a content defined function from chrome (or it can be a getter too) and the function is executed with chrome privileges accidentally. But for example content can navigate the page or do something else it had originally permission to do, when we expect it to do something completely different.

In general you want to avoid using this property, and if you really need this functionality you should use XPCNativeWrapper.unwrap, since it will work even if your object is not an XrayWrapper (I repeat: XPCNativeWrapper == XrayWrapper). Implementation wise, this function wraps the object in it’s own compartment in a so called WaiveXrayWrapperWrapper, which is a fully transparent wrapper, and unlike wrappers so far the proxy and the original object are in the same compartment. And then when an XrayWrapper is created for it in the chrome compartment, this wrapper will be detected and we won’t apply an XrayWrapper, more precisely a transparent wrapper called  SafeJSObjectWrapper (see below) will be applied.

The reason why you should prefer the unwrap function over the wrappedJSObject property is because just to make it more confusing wrappedJSObject might mean something else. It can be just a simple property of course, or, if there is a (COM) component implemented in javascript, then instead of the object itself a wrapper of it will be exposed to javascript that is using the component. This way it will act like any other native implementation of the component (interfaces). So the caller will not have access to anything other then the original implementation of the interfaces. So in some cases we want to access the underlying javascript object directly, and for some reason we use wrappedJSObject property here too. These looks like a confusing naming conflict… and it is. So this second use of wrappedJSObject was first, and unfortunately I don’t quite know the story behind it. But the symmetry behind the two cases is pretty obvious, so it’s not hard to guess why was the same name reused in XPCNativeWrapper. Anyway in practice I think this can be quite confusing if we are not aware of it.

And there is a 3rd wrapper in this category which is a little bit harder to grasp, it’s the SafeJSObjectWrapper (SJOW).  It is for the case where chrome wants to access a non-native object from web content or in some cases where we want to avoid using the restricting XrayWrapper. Now what we want to avoid here is some property getter function being executed in a chrome privileged context accidentally. It’s simply a transparent wrapper and its only purpose is to prevent some content defined function to be executed with chrome privileges, what you should never want to do anyway.

Note: In the code it is called: CrossOriginWrapper, and it is NOT the wrapper that is dealing with the case when content from one origin is exposed to a content from another origin and referred to as XOW  (Cross-OriginWrapper in the docs).

Wrappers between content and content

Cross-OriginWrapper (XOW)

There are cases where content needs to interact with other content, for example when a script interacts with some objects from an iframe. In this case the Cross-OriginWrapper will be applied. We distinguish two cases. The first and simplest case when both scripts have the same origin (the iframe is from the same domain as the original for example). In this case the wrapper is as transparent as possible. In the second case the domains are different, it will be more restrictive. It is basically the combination of an XrayWrapper and a short hardcoded white list of allowed property accesses.

Note: It is important to keep in mind when looking at the actual code, that CrossOriginWrapper class is totally different, and we are talking about  XOW here (which is unfortunately the short term for the same name) and it is a filtering proxy defined in FilteringWrapper.cpp.

SystemOnlyWrapper (SOW)

And the last case is a very special case. When native anonymous content is exposed to JS, it will be wrapped into a SystemOnlyWrapper, which denies every access unless it comes from chrome. This was introduced for XBL so that XBL elements when cloned into a web page can access native anonymous content from JS (which is not even visible normally from regular content).

Now that we have some grasp of each security wrapper’s role let see  what restrictions they come with.

Restrictions per wrapper:

XrayWrapper

From a javascript developer perspective, XrayWrappers are the most tricky ones. In a nutshell: if the underlying object is a native property, it can be called or accessed.  Expando properties are allowed on the wrapper, which means you can set a new property like myXrayWrappedObject.foo = 42; and that  property will be visible from the chrome side, but not from the content side (since it will be set on the wrapper instead of the actual object the wrapper proxy to). This can be a very confusing behavior. Especially that some other properties that might have a native getter, will operate directly on the content… If that is not confusing enough, unfortunately there are some more limitations. One of is that .call and .bind will not work as expected. Currently they will simply ignore the |this| argument and use the original object (the method was fetched from) as |this|. I’ve been trying to fix this bug for a while but it is not that simple to resolve for various reasons.

ChromeObjectWrapper

So in short, if a function object is exposed to content, it can be called. Anything other property access is blocked and an exception is thrown. Alright. There are exceptions of course. The length property of exposed arrays is available as well as the array operator [] on them. And if we do want to expose other properties on purpose, we can define a white list of properties via the __exposedProps__ property on chrome side. Like exportedObject.__exposedProps__ = { foo: “r” }; where foo is the name of the property we let the content access and “r” means read only, “w” write only, and “rw” read write access.

Yes, this means unfortunately that __proto__ does not work either, which means instanceof will not work either… Or if the exported object is a method, exportedMethod.call / .bind will fail and even .toString()… Enabling access to bind and call of the chrome compartment, would be a free ticket to evaluate content code with chrome privileges. There is a workaround…. it is quite far from a perfect solution for the problem and probably this part should be improved in the future, but here it is.http://mxr.mozilla.org/mozilla-central/source/js/xpconnect/tests/chrome/test_APIExposer.xul#28

SafeJSObjectWrapper

No real restrictions.

Cross-OriginWrapper (XOW)

This one is well… interesting. Simply put, it is a hardcoded white list of properties. So calling an exported method is allowed and anything else that is not from this white list is blocked.

object = DOMException

read/write:  “code”, “message”, “name”, “result”

read only: “toString”

object =  Error

read only: “message”

object = History

read only “back”, “forward”, “go”

object = Location

write only: “hash”, “href”

read only: “replace”

object = Window

read only: “blur”, “close”, “closed”, “focus”, “frames”, “history”, “length”, “opener”, “parent”, “postMessage”, “self”, “top”, “window”

read/write: “location”

So for example, if we have a reference to a window from another domain, we can have read access to its postMessage method, and since postMethod is a method, we can call it. Furthermore,  this wrapper also provides XrayWrapper behavior for the allowed operations.

In the same origin case it is simply transparent.

SystemOnlyWrapper:

So if we are some chrome code or some system call, or some code loaded from chrome://global/ (XBL stuff), or the script has UniversalXPConnect privileges (usually some old tests) then the property access is allowed, any other case exception is thrown.