Components.utils.evalInSandbox

  • Revision slug: Components.utils.evalInSandbox
  • Revision title: Components.utils.evalInSandbox
  • Revision id: 101233
  • Created:
  • Creator: SylvainPasche
  • Is current revision? No
  • Comment 386635 backed out

Revision Content

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 a principal URI. This URI is used for same-origin security checks. For example, passing a URI of http://www.example.com/ will allow code evaluated using this sandbox to access data from http://www.example.com. Due to the ability of JavaScript on a web page to set document.domain, changing same-origin security checks, you can also pass a DOM window object to the sandbox constructor.

// create a sandbox with a given principal
var s = Components.utils.Sandbox("http://www.example.com/");
// the sandbox object is the global scope object
// for script you execute
s.y = 5;
var result = Components.utils.evalInSandbox("x = y + 2; x + 3", s);
// result is 10, s.x is now 7

s.foo = Components;
// this will give a "Permission Denied" error
Components.utils.evalInSandbox("foo.classes", s);

Note {{template.Bug(350558)}}.

Security

Security warning: There is potential for security problems to arise when using evalInSandbox() if you rely on the properties of an object resulting from the code executed in the sandbox.

Some examples:

<script src="prototype.js"></script>

<script>
var s = new Components.utils.Sandbox(url);
var x = Components.utils.evalInSandbox(untrusted_code, s);
if (x == 1) {
  /* this code is unsafe; calls x.valueOf() */
}

if (x === 1) {
  /* this code is safe */
}

var y = x.y; /* this is unsafe */
var z = sandbox.z; /* unsafe */

if (typeof x == "number") {
  /* safe */
}
</script>

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.

{{ wiki.languages( { "ja": "ja/Components.utils.evalInSandbox" } ) }}

Revision Source

<p>
</p>
<h3 name="Introduction"> Introduction </h3>
<p>In certain circumstances, you may want to evaluate <a href="en/JavaScript">JavaScript</a> code with restricted privileges.  In <a href="en/Firefox_1.5">Firefox 1.5</a> (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.
</p>
<h3 name="Use"> Use </h3>
<p>To use <code>evalInSandbox()</code>, you must first create a sandbox object using its constructor, <code><a href="en/Components.utils.Sandbox">Components.utils.Sandbox</a></code>.  The sandbox must be initialized with a principal URI.  This URI is used for same-origin security checks.  For example, passing a URI of <code><span class="plain">http://www.example.com/</span></code> will allow code evaluated using this sandbox to access data from <span class="plain">http://www.example.com</span>.  Due to the ability of JavaScript on a web page to set <code><a href="en/DOM/document.domain">document.domain</a></code>, changing same-origin security checks, you can also pass a DOM window object to the sandbox constructor.
</p>
<pre>// create a sandbox with a given principal
var s = Components.utils.Sandbox("http://www.example.com/");
// the sandbox object is the global scope object
// for script you execute
s.y = 5;
var result = Components.utils.evalInSandbox("x = y + 2; x + 3", s);
// result is 10, s.x is now 7

s.foo = Components;
// this will give a "Permission Denied" error
Components.utils.evalInSandbox("foo.classes", s);
</pre>
<p>Note {{template.Bug(350558)}}.
</p>
<h3 name="Security">Security</h3>
<div class="warning"><b>Security warning:</b> There is potential for security problems to arise when using <code>evalInSandbox()</code> if you rely on the properties of an object resulting from the code executed in the sandbox.</div>
<p>Some examples:
</p>
<pre class="eval">&lt;script src="prototype.js"&gt;&lt;/script&gt;

&lt;script&gt;
var s = new Components.utils.Sandbox(url);
var x = Components.utils.evalInSandbox(untrusted_code, s);
if (x == 1) {
  /* this code is unsafe; calls x.valueOf() */
}

if (x === 1) {
  /* this code is safe */
}

var y = x.y; /* this is unsafe */
var z = sandbox.z; /* unsafe */

if (typeof x == "number") {
  /* safe */
}
&lt;/script&gt;
</pre>
<p>To understand how the security risk arises, let's take the example of <code>(x == 1)</code>.  When this is evaluated, the <code>x.valueOf()</code> method gets called by chrome code.  When this happens, unsafe code can create a String object in the chrome code's global scope.
</p><p>If the chrome code has added a function that has chrome privileges to <code>String.prototype</code>, <code>Object.prototype</code>, or <code>Function.prototype</code>, 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.
</p><p>To avoid this potential security risk, you should either carefully avoid using objects resulting from <code>evalInSandbox()</code> 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 <code>evalInSandbox()</code> to evaluate them.
</p>{{ wiki.languages( { "ja": "ja/Components.utils.evalInSandbox" } ) }}
Revert to this revision