XPConnect Chrome Object Wrappers: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
(added link to bug 518991)
Line 81: Line 81:


   http://hg.mozilla.org/users/avarma_mozilla.com/cow-exposed-info/
   http://hg.mozilla.org/users/avarma_mozilla.com/cow-exposed-info/
== Related Bugzilla Bugs ==
* [https://bugzilla.mozilla.org/show_bug.cgi?id=518991 518991 - COWs should only expose certain properties]

Revision as of 19:10, 11 October 2009

Introduction

Chrome Object Wrappers, or COWs for short, allow privileged code to securely expose some subset of its functionality to untrusted or semi-trusted content.

The COW is actually the final step in an epic quest to make the interaction between chrome and content as natural and secure as possible by encasing JavaScript objects in "membranes" that mediate access between their object and the outside world. Before reading the rest of this document, you should be familiar with the story so far, which is explained in detail at XPConnect wrappers.

Usage

COWs are always created automatically as necessary whenever an object passes through a trust boundary. This is in keeping with the philosophy that "the default should be secure": if writing secure code is optional, developers are burdened because they always need to remember how to write securely.

Also in keeping with this philosophy, however, is the notion that we don't want to expose chrome data or functionality to untrusted code unless the developer explicitly provides permission to do so. This is lexically enforced through the use of metadata, as will be shown shortly.

COWing Functions

Assume the following chrome-privileged code:

const Cu = Components.utils;

function foo(obj) {
  /* Do something here that requires chrome privileges. */
}
foo.__callableByContent__ = true;

var sandbox = Cu.Sandbox("http://www.mozilla.org");
sandbox.foo = foo;
var result = Cu.evalInSandbox("foo({bar: 5});");

In the above example, foo() is wrapped by a COW when accessed by sandboxed code executed via Components.utils.evalInSandbox(). The object {bar: 5} is wrapped in an XPCSafeJSObjectWrapper before being passed into foo().

The metadata attached to foo(), __callableByContent__, is used to explicitly declare that the function its attached to can be called from content. This is necessary for security purposes; if a function that's only ever intended to be called from trusted code ever accidentally "falls into the wrong hands", we don't want untrusted code to be able to exploit it.

If a function without __callableByContent__ is called from content, a JS Error is raised with the text "function is not callable from content".

COWing Objects

By default, Chrome objects passed into content space are completely opaque: no information can be accessed from them, and no properties can be defined on them.

TODO: What happens on read/write of properties on such objects? Is an exception raised, or do all reads simply return undefined and are all writes null-ops?

Individual properties can be exposed by defining a __exposedProps__ property on the object, like so:

const Cu = Components.utils;

var MyObj = {
  __exposedProps__ = {foo: "r", bar: "rw"},

  foo: function foo(obj) {
    /* Do something here that requires chrome privileges. */
  },

  bar: "supdog",

  baz: "I am protected information"
}

MyObj.foo.__callableByContent__ = true;

In the above example, MyObj.foo() can be accessed but not assigned to—and foo() itself is callable from content, since __callableByContent__ is set—and MyObj.bar is both readable and writable, while MyObj.baz can't be accessed at all.

If any property is accessed that isn't in __callableByContent__—even if the property doesn't even exist on the original object—then a JS Error is raised with the text "property not accessible from content".

All properties that are exposed to content are enumerable by content as well.

TODO: What should the default toString() method of a COW'ed object with no metadata yield?

TODO: Does this work okay with getters and setters?

TODO: If a property is writable by content, is it deletable by content as well?

TODO: Discuss what to do with native objects that get exposed (like the Sidebar object).

Compliance Tests

TODO: Write a compliance test suite. It should allow us to implement COWs in C++ as well as in JS (via Flexible Membranes) using test-driven development.

A work-in-progress suite of compliance tests for the metadata functionality of COWs can be found at:

 http://hg.mozilla.org/users/avarma_mozilla.com/cow-exposed-info/

Related Bugzilla Bugs