One of the recurring issues that the Mozilla platform team has to contend with is the issue of how to allow trusted, privileged JavaScript code to interact with untrusted JavaScript code. Google’s Caja team actually has to deal with a very similar problem, albeit at a different layer in the technology stack.
This issue is quite subtle, and fully explaining it is beyond the scope of this blog post. If you know JavaScript, I recommend checking out the Caja Specification, which nicely lays out the problems inherent in running code with different trust levels in the same environment.
Firefox has to deal with this issue because much of it is actually written in JavaScript. Developers call the JS that powers Firefox chrome JavaScript: it has the ability to write to the filesystem, launch other programs on your computer, and pretty much anything that Firefox itself can do. The code that runs in web pages, on the other hand, is called content JavaScript. Chrome and content JS can interact with each other securely thanks to XPConnect wrappers: little layers of code that “wrap” objects and mediate access between them and the outside world. The self-proclaimed WrapMaster and implementer of most of these wrappers is Blake Kaplan, known in some circles as “Mr. B-Kap” (mrbkap).
Google Caja’s team also has a need for the same kind of functionality, but at a different level: they need to make it possible for web pages themselves able to run code that they don’t trust, which is useful when creating plug-in frameworks for web applications. The Caja team calls wrappers membranes—a word which I find more intuitive than “wrappers” because it’s not an overloaded term in computer science and because its biological definition closely matches that of its CS counterpart.
As I wrote in Jetpack: Summer 2009 State of Security, Part 1, the boundary between trusted and untrusted code has been of some concern to the Jetpack project. Unfortunately, all the XPConnect wrappers currently in Firefox have very specific purposes: for instance, most of them are made expressly to prevent omnipotent chrome code from being exploited by impotent content code. Jetpack’s needs are unique in that a Jetpack feature should be neither as omnipotent as Firefox, nor as impotent as a web page: ideally, we should follow the principle of least privilege and give it the minimum set of capabilities it needs to do its task, and no more.
After talking with the Firefox JS and Google Caja teams, we decided that wrappers were the right kind of solution to Jetpack’s security challenges. The problem was, though, that all of Firefox’s wrappers are in C++, which made them hard to experiment with. Jetpack is, after all, a Labs project, and as such, we needed a sort of “flexible membrane” whose security characteristics we could easily change as the platform evolved. So we decided to expose some functionality to chrome JavaScript that’s traditionally only available to C/C++ code.
One nice aspect of the flexible membranes we’ve created is that they’re useful for more than just prototyping membranes: they effectively allow chrome JS to create objects with characteristics that the JavaScript language doesn’t traditionally make room for, like catch-alls for object properties. Python programmers know of these by names like __getattr__ and __setattr__, and many other dynamic languages have them, but JavaScript doesn’t—yet something like them is needed to implement basic Web APIs like HTML5 localStorage. In other words, these flexible membranes should make it easy for us to develop nicer APIs for Jetpack.
If you’re interested in digging into these flexible membranes, check out our Binary Components documentation on the wiki. And feel free to take the pre-compiled component from our HG repository and use it in your own Firefox extensions.
My name is Atul Varma, and I'm the co-founder of a small Chicago company called 






The big question for me is: can we use something like Caja to make it possible for people to create jetpacks or even addons which other people can install without them needing a security code review? That would be an enormous step forward in allowing us to scale the addons community.
(If that’s what you are actually talking about here then you have successfully buried the lead
Gerv
Yep, that’s exactly where we’re headed, Gerv—more on that in the next blog post!
Yo Atul,
How might out-of-process extensions change the parameters of this problem? In that case you potentially have content and chrome javascript on opposite sites of an IPC boundary…
curiously,
lloyd
Good question, Lloyd. There’s basically three main factors here that I can think of.
The main one, which was a design goal when creating the Jetpack prototype back in May, was that staying in-process–and in particular, staying in the same thread that ran a web page’s user interface and all its attending JS code–was good for developer ergonomics, especially insofar as “casual developers” were concerned. The code examples in the Jetpack Tutorial basically attest to this: they’re single script chunks that are easy to read and understand because all the code is executing in the same thread, global scope, and process. It’s possible that the same scripts could be run in a multi-process environment–in fact, it’s something we’re addressing as the Electrolysis project moves forward–but it’ll raise all kinds of issues regarding flow control and cross-process garbage collection.
This brings us to the second factor, which is that the Mozilla platform has been moving in the direction of membranes/wrappers for the past few years, so doing everything in one process and using membranes was very much following the trajectory that the Mozilla platform team was already taking. On the other hand, the Mozilla platform doesn’t have much functionality for IPC, so we’d be building a lot of infrastructure “from scratch”. In other words, going the membrane route played to our strengths rather than our weaknesses.
The last factor comes from viewing Jetpack as an experiment: Chrome Extensions are already doing lots of cool multiprocess work, and going the multiprocess route ourselves would basically mean that we’d be “reinventing the wheel” that Chrome Extensions was already building, which means that Jetpack wouldn’t have much value as an experiment. The membrane route, OTOH, is something that AFAIK nobody else is trying, and as such it’s something that we’ve potentially got a lot to learn from, regardless of how successful Jetpack ends up being.
(I’d like to note, though, that the last point is totally separate from the notion that Firefox should support the Chrome Extension API, which I think would be a huge win.
Write once, run in any browser FTW!)
Hey Atul,
To the first point, it’s interesting to think about the potential impact of a process break on developer ergonomics. Specifically, what sorts of specific freedom in JetPack API design do you perceive might be lost in the process break? DOM manipulation? Introduction of more asynchronicity in the API?
As to your second point, it makes sense that you’d be wading into uncharted, perhaps risky territory. But OTOH, there are certain benefits to be had. Specifically, all of the motivations of the Electrolysis project apply (simplified resource monitoring, crash resilience, reclaimation, as well as forwards compatibility with a more proccessy firefox). Finally, this is a very powerful way to ensure that the requirements of the JetPack runtime on the underlying browser are isolated and easily discoverable :P…
And your last point is perhaps the most compelling. If the goal of JetPack is to vigorously explore a new plugin authoring environment, then anything that significantly slows that effort without yielding new knowledge should be eliminated…. I buy it.
Finally, theres’ a ton of context here I’m missing, so bear with me as I take uncertain first steps
lloyd