Components.utils.evalInSandbox

Introduction

In certain circumstances, you may want to evaluate JavaScript code with restricted privileges. In Firefox 1.5 (Gecko 1.8) or later, an API exists to allow you to do this. It contains the notion of a "sandbox" that you can create and evaluate code in its context. Code evaluated using this method will always execute with restricted privileges, as on a normal web page.

Use

To use evalInSandbox(), you must first create a sandbox object using its constructor, Components.utils.Sandbox. The sandbox must be initialized with either an origin URI or preferably a DOM window (nsIDOMWindow, like the window object in a web page). In Firefox 3 (Gecko 1.9) or later, it can also be initialized with an nsIPrincipal object. Using an nsIPrincipal is preferable to using an origin URI. This URI, window, or nsIPrincipal is used as the origin of the string being evaluated for all security purposes (e.g. for same-origin security checks). For example, passing a URI of http://www.example.com/ will allow code evaluated using this sandbox to make AJAX requests from http://www.example.com. If the JavaScript you run in the sandbox sets document.domain, that is it changes the same-origin security checks, you should pass a DOM window object or nsIPrincipal to the sandbox constructor rather than a URI.

Here is an example with a URI:

// create a sandbox with a given origin URI
var s = Components.utils.Sandbox("http://www.example.com/");

The sandbox is just an empty JavaScript object marked as being created by the restricted privilege principal. It will become the global scope object when you pass it to evalInSandbox(text, sandbox). You may want to add objects to this scope. Continuing the example:

To understand how the security risk arises, let's take the example of (x == 1). When this is evaluated, the x.valueOf() method gets called by chrome code. When this happens, unsafe code can create a String object in the chrome code's global scope.

If the chrome code has added a function that has chrome privileges to String.prototype, Object.prototype, or Function.prototype, then unsafe code can abuse that function. What the unsafe code can do depends on what that function is, but the unsafe code can wind up being executed with chrome privileges.

To avoid this potential security risk, you should either carefully avoid using objects resulting from evalInSandbox() in any way that might result in a function in that object being called, or you should make sure that untrusted JSON strings don't contain any functions or expressions before using evalInSandbox() to evaluate them.