We discussed at the first Ubiquity planning meeting that we need to come up with and implement a security model for the next release, so I thought I’d write down a few thoughts I’ve been having about it. I don’t consider myself a security expert by any stretch of the imagination, though, so any suggestions or corrections are more than welcome.
Firstly, as noted in the meeting notes, the notion of a security model being discussed here is separate from, but supporting of, the kind of social “web of trust” based model that I’ve written about before. Being able to easily communicate to someone with technical expertise that a piece of functionality will only be able to have a certain level of access to their system can be an excellent aid in determining whether they want to risk trying it out, and this in turn can affect whether they ultimately recommend it to other less technical members of their trust network.
Looking at the current state of mechanisms that allow people to “remix the web”, there appear to be a number of security models out there:
- Bookmarklets are run in the context of the web page that they're activated on; they can't do anything that the web page they're running on can't. While this means that they won't be able to access the filesystem or anything, it does mean that they can potentially abuse any sensitive information contained on the webpage itself. In Firefox security parlance, a script with this kind of limited access is referred to as "running with content privileges."
- Greasemonkey Scripts, to my understanding, run in a sandboxed environment that has full access to the web page they operate on via XPCNativeWrappers, as well as special access to more limited functionality via GM_* functions. Consequently, a malicious GreaseMonkey script could do more than a malicious Bookmarklet, but not nearly as much damage as a malicious client-side executable.
- Firefox Extensions are not sandboxed in any way; as such, they have the same privileges as the Firefox process that contains them, which usually means that they can do whatever they want to your computer. In Firefox security parlance, this is referred to as "running with chrome privileges."
At present, while Ubiquity command feeds are technically sandboxed via Components.utils.Sandbox instances, the sandboxes are currently initialized using a security principal that gives them chrome privileges. On top of that, even if they were initialized with a more limited principal providing only content privileges, they’re currently accessed insecurely. Both of these aren’t very hard to change, though; the primary challenge will be determining a security model that’s best for Ubiquity’s needs.
One solution may be to have each command feed choose from one of many security model selections. For instance, a command feed’s metadata could specify one of the following security levels:
- Greater Chrome command feeds execute with full chrome privileges (i.e., how command feeds are currently executed).
- Lesser Chrome command feeds execute with Greasemonkey-like privileges, whereby they have secure access to untrusted content and limited access to chrome functionality, such as cross-site XHR's. It's possible that extra metadata could specify exactly what subset of chrome features the command feed has; for instance, one command feed might request only that it have the additional access to make XHR requests to two particular domains. Care, however, must be taken to ensure that this "security manifest" isn't so complex that it makes understanding the security implications of a command script difficult and error-prone.
- Greater Content command feeds execute with Bookmarklet-like privileges.
- Lesser Content command feeds only have the ability to examine the current selection and replace it. This could be useful for commands like "uppercase."
For the sake of experimentation and exploration, it may even be useful to make security models “pluggable”, so that anyone can write their own security model, which can then be used to limit the privileges of any command feed that runs under it.
As a place to start, I’ve created a new safebox.js JS module in the Ubiquity repository that provides a safe interface to communicate with a Components.utils.Sandbox running untrusted code in xpcshell or an XULRunner application (e.g., Firefox or Thunderbird). All data going into and out of the sandbox is marshalled using JSON, and all communication is synchronous. Sample unit test code can currently be found in safebox_tests.js. I’d also like to thank Blake Kaplan for explaining some of the underpinnings of the Spidermonkey and XPConnect security models to me, as well as assisting in the debugging of some strange XPCSafeJSObjectWrapper behavior under xpcshell.
If anyone has any feedback on what’s been described here, I’d love to read it.