Components.utils.Sandbox
is used to create a sandbox object for use with evalInSandbox()
.
Creating a sandbox
To create a new sandbox, call Components.utils.Sandbox
:
var sandbox = Components.utils.Sandbox(principal[, options]);
Using new Components.utils.Sandbox(...)
to create a sandbox has the same effect as calling Sandbox(...)
without new
.
The created sandbox is simply an empty JavaScript object marked as having been created by the restricted privilege principal. You can then use it with evalInSandbox()
to make it the global scope object for the specified script.
principal
The security principal defined for a sandbox determines what code running in that sandbox will be allowed to do. The principal may be one of four types: the system principal, a content principal, an expanded principal, or a null principal.
See Security checks for more information on security principals.
System principal
To specify the system principal, you can create it using code like:
Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal);
Content principal
You can specify a content principal for a particular origin in one of three ways:
- as an
nsIPrincipal
, for example by using thenodePrincipal
property of a DOM node - as an
nsIDOMWindow
, such as that returned by the DOMwindow
property - as a string URI like "http://www.example.com/" (discouraged)
When possible, specify a window or an nsIPrincipal
object instead of using a string URI. Window objects and nsIPrincipal
carry additional information such as origin attributes and same-origin privilege changes caused by setting document.domain
.
Example of obtaining content principal from the window:
var principal = gBrowser.selectedTab.linkedBrowser.contentPrincipal; var sandbox = Components.utils.Sandbox(principal);
Expanded principal
An expanded principal is specified as an array of the principals it subsumes. Each item in the array should be an nsIPrincipal
, a DOM window, or a URI. So this can be simply an array with a single element. For example the content principal above can be made expanded/extended like so:
var principal = [gBrowser.selectedTab.linkedBrowser.contentPrincipal]; // this is now an expanded (aka extended) principal var sandbox = Components.utils.Sandbox(principal);
Null principal
You can create a null principal using code like:
Cc["@mozilla.org/nullprincipal;1"].createInstance(Ci.nsIPrincipal);
From Firefox 37 onwards, you can also specify the null principal by simply passing null
as the principal
argument.
options
The constructor accepts an optional parameter. This parameter is an object with the following optional properties:
freshZone
Requires Gecko 40.0- If true creates a new GC region separate from both the calling context's and the sandbox prototype's region. Addons creating sandboxes whose expected lifetime is tied to that of a content
window
object will want to usesameZoneAs
instead.
sameZoneAs
- A JavaScript object in whose garbage collection region the sandbox should be created in. This helps to improve memory usage by allowing sandboxes to be discarded when that zone goes away. Content scripts should pass the
window
they're running in as this parameter, in order to ensure that the script is cleaned up at the same time as the content itself. sandboxName
-
A string value which identifies the sandbox in about:memory (and possibly other places in the future). This property is optional, but very useful for tracking memory usage of add-ons and other JavaScript compartments. A recommended value for this property is an absolute path to the script responsible for creating the sandbox. As of Gecko 13 (Firefox 13.0 / Thunderbird 13.0 / SeaMonkey 2.10), if you don't specify a sandbox name it will default to the caller's filename.
sandboxPrototype
-
A prototype object for the sandbox. The sandbox will inherit the contents of this object if it's provided.
Passing a contentwindow
object, settingwantXrays:true
(default) and using an extended principal provides a clean, isolated execution environment in which javascript code that needs Web APIs (such as accessing the window's DOM) can be executed without interference from untrusted content code. wantComponents
-
A Boolean indicating whether the
Components
object is available or not in the sandbox. Default:true
.
If the sandbox interacts with untrusted content this should be set tofalse
when possible to further reduce possible attack surface. wantExportHelpers
-
A Boolean: if true, then
createObjectIn()
,evalInWindow()
, andexportFunction()
are available in the sandbox. Default:false
. wantGlobalProperties
- An array of strings. Each string is the name of an object that you want to make available as a global to code running in the sandbox.
- The exception is "
-Promise
": thePromise
constructor is available by default for sandboxes, and you use this option to remove it from the sandbox. Note that"-Promise"
is removed in Firefox 37. - The following objects are supported:
-
-Promise
(removed in Firefox 37)CSS
indexedDB (Web Worker only)
XMLHttpRequest
TextEncoder
TextDecoder
URL
URLSearchParams
atob
btoa
Blob
File
crypto rtcIdentityProvider
fetch
(added in Firefox 41)caches FileReader For example:
var sandboxScript = 'var encoded = btoa("Hello");' + 'var decoded = atob(encoded);'; var options = { "wantGlobalProperties": ["atob", "btoa"] } var sandbox = Components.utils.Sandbox("https://example.org/", options); Components.utils.evalInSandbox(sandboxScript, sandbox); console.log(sandbox.encoded); // "SGVsbG8=" console.log(sandbox.decoded); // "Hello"
wantXHRConstructor
- This option was removed in Gecko version 26. Use
wantGlobalProperties
instead. wantXrays
-
A Boolean value indicating whether the sandbox wants Xray vision with respect to same-origin objects outside the sandbox. Default:
true
.Setting
wantXrays
tofalse
also causes Xrays to be waived on objects in the sandbox. If you are creating a sandbox with lower privileges than the current compartment, this is probably not what you want.“Xray vision” is exactly the same Xray behavior that script always gets, by default, when working with DOM objects across origin boundaries. This is primarily visible for chrome code accessing content. However, it also occurs during cross-origin access between two content pages, since each page sees a "vanilla" view of the other. The protection is bidirectional: the caller sees the bonafide DOM objects without being confused by sneakily-redefined properties, and the target receives appropriate privacy from having its expandos inspected by untrusted callers. In situations where only unidirectional protection is needed, callers have the option to waive the X-ray behavior using
wrappedJSObject
orXPCNativeWrapper.unwrap().
In general, when accessing same-origin content, script gets a Transparent wrapper rather than an Xray wrapper. However, sandboxes are often used when chrome wants to run script as another origin, possibly to interact with the page. In this case, same-origin Xrays are desirable, and
wantXrays
should be set totrue
.See Safely accessing content DOM from chrome for more details.
Methods available on the Sandbox object
dump()
- Similar to window.dump().
debug()
For more information on the built-in Sandbox functions, please consult the source code.
Importing functions or objects into the sandbox
You can import functions or objects into the sandbox simply by assigning them to the sandbox object. For example:
mysandbox.doSomething = function() { ... };
Complex objects can be cloned into the sandbox using Components.utils.cloneInto
:
mysandbox.someObject = Components.utils.cloneInto({ a: 'string', b: 21 }, mysandbox);
Obviously you need to consider the security implications of the functions you import. This technique isn't limited to functions - it can be used to import objects or values.
Freeing the sandbox
When you have finished using a sandbox, it should be freed to avoid memory leaks. Generally the JavaScript garbage collector will take care of this when there are no remaining references to the sandbox or the code it contains. However, in some cases it can be difficult to remove all references. For example, the code in the sandbox might be a third-party library that sets expando properties or adds event listeners to a window. In this case, Components.utils.nukeSandbox
can be used to force the sandbox to be freed immediately.
Example
Executing in current tab scope
More ways to load scripts into a sandbox can be found on the Loading Scripts page.
This example is to be run from scratchpad with environemnt set to browser. It alerts the dollar sign function. This code was tested on twitter.com and gets access to the jQuery $.
var sandboxScript = 'alert($)'; var options = { sandboxPrototype: content, wantXrays: false // only set this to false if you need direct access to the page's javascript. true provides a safer, isolated context. }; var sandbox = Cu.Sandbox(content, options); Cu.evalInSandbox(sandboxScript, sandbox); Cu.nukeSandbox(sandbox);