Bug 1322862 - Make __webDriverArguments et al. content safe; r=automatedtester

Properties created in a more privileged scope than content cause
permission denied errors when they are accessed from a less privileged
scope.  This is the case when we assign a document unload handler from
chrome to a sandbox with content privileges.  A permission denied error
will be thrown if this handler is inspected from the code evaluated
inside the sandbox.

By cloning the properties along with their functions and wrapping their
reflectors, we can ensure they can be safely inspected from content.

MozReview-Commit-ID: Hy5MYvdTsv8

--HG--
extra : rebase_source : 068cd67f3bc6f99c312303c4682c47cd9c5143d7
This commit is contained in:
Andreas Tolfsen 2016-12-10 16:15:53 -10:00
Родитель d9f19d9e12
Коммит 5a917f7627
2 изменённых файлов: 31 добавлений и 7 удалений

Просмотреть файл

@ -113,7 +113,7 @@ evaluate.sandbox = function (sb, script, args = [], opts = {}) {
if (opts.async) {
sb[CALLBACK] = sb[COMPLETE];
}
sb[ARGUMENTS] = Cu.cloneInto(args, sb, {wrapReflectors: true});
sb[ARGUMENTS] = sandbox.cloneInto(args, sb);
// callback function made private
// so that introspection is possible
@ -138,20 +138,18 @@ evaluate.sandbox = function (sb, script, args = [], opts = {}) {
// see bug 1128760 for more details
if (opts.debug) {
sb.window.onerror = (msg, url, line) => {
let err = new JavaScriptError(`${msg} at: ${url} line: ${line}`);
let err = new JavaScriptError(`${msg} at ${url}:${line}`);
reject(err);
};
}
// timeout and unload handlers
scriptTimeoutID = setTimeout(
timeoutHandler, opts.timeout || DEFAULT_TIMEOUT);
sb.window.addEventListener("unload", unloadHandler);
scriptTimeoutID = setTimeout(timeoutHandler, opts.timeout || DEFAULT_TIMEOUT);
sb.window.onunload = sandbox.cloneInto(unloadHandler, sb);
let res;
try {
res = Cu.evalInSandbox(
src, sb, "1.8", opts.filename || "dummy file", 0);
res = Cu.evalInSandbox(src, sb, "1.8", opts.filename || "dummy file", 0);
} catch (e) {
let err = new JavaScriptError(
e,
@ -176,6 +174,18 @@ evaluate.sandbox = function (sb, script, args = [], opts = {}) {
this.sandbox = {};
/**
* Provides a safe way to take an object defined in a privileged scope and
* create a structured clone of it in a less-privileged scope. It returns
* a reference to the clone.
*
* Unlike for |Components.utils.cloneInto|, |obj| may contain functions
* and DOM elemnets.
*/
sandbox.cloneInto = function (obj, sb) {
return Cu.cloneInto(obj, sb, {cloneFunctions: true, wrapReflectors: true});
};
/**
* Augment given sandbox by an adapter that has an {@code exports}
* map property, or a normal map, of function names and function

Просмотреть файл

@ -262,6 +262,17 @@ class TestExecuteContent(MarionetteTestCase):
content_timeout_triggered,
message="Scheduled setTimeout event was cancelled by call to execute_script")
def test_privileged_code_inspection(self):
# test permission denied on toString of unload event handler
self.marionette.navigate(inline("""
<script>
window.addEventListener = (type, handler) => handler.toString();
</script>"""))
self.marionette.execute_script("", sandbox=None)
# test inspection of arguments
self.marionette.execute_script("__webDriverArguments.toString()")
class TestExecuteChrome(WindowManagerMixin, TestExecuteContent):
@ -337,6 +348,9 @@ class TestExecuteChrome(WindowManagerMixin, TestExecuteContent):
def test_window_set_timeout_is_not_cancelled(self):
pass
def test_privileged_code_inspection(self):
pass
class TestElementCollections(MarionetteTestCase):