зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1353074 - Make unload event safe for introspection from content; r=maja_zf
Marionette does not protect the unloadHandler in testing/marionette/evaluate.js from content introspection or modification, which can happen when web frameworks override window.addEventListener/window.removeEventListener. The script evaluation module used in Marionette relies on sandbox.window.addEventListener/removeEventListener to throw an error when script execution is aborted due to the document unloading itself. If the window.addEventListener/removeEventListener functions have been overridden to introspect the objects that are passed, they may inadvertently touch objects originating from chrome space, such as the unloadHandler. Because the Gecko sandboxing system put in place strict security measures to prevent accidental chrome-space modification from content, inspecting the unloadHandler will throw a permission denied error once the script has finished executing. We have found examples in the wild of this in particular with the Angular web framework. This patch makes the unloadHandler safe for introspection from web content. Fixes: https://github.com/mozilla/geckodriver/issues/515 MozReview-Commit-ID: E2LgPhLLuDT --HG-- extra : rebase_source : c7431630d24c42ebfd7ded3cf204c1ef245211d0
This commit is contained in:
Родитель
f6660740ac
Коммит
3e559119d6
|
@ -105,8 +105,9 @@ evaluate.sandbox = function (sb, script, args = [], opts = {}) {
|
|||
let src = "";
|
||||
sb[COMPLETE] = resolve;
|
||||
timeoutHandler = () => reject(new ScriptTimeoutError("Timed out"));
|
||||
unloadHandler = () => reject(
|
||||
new JavaScriptError("Document was unloaded during execution"));
|
||||
unloadHandler = sandbox.cloneInto(
|
||||
() => reject(new JavaScriptError("Document was unloaded during execution")),
|
||||
sb);
|
||||
|
||||
// wrap in function
|
||||
if (!opts.directInject) {
|
||||
|
@ -145,7 +146,7 @@ evaluate.sandbox = function (sb, script, args = [], opts = {}) {
|
|||
|
||||
// timeout and unload handlers
|
||||
scriptTimeoutID = setTimeout(timeoutHandler, opts.timeout || DEFAULT_TIMEOUT);
|
||||
sb.window.onunload = sandbox.cloneInto(unloadHandler, sb);
|
||||
sb.window.addEventListener("unload", unloadHandler);
|
||||
|
||||
let res;
|
||||
try {
|
||||
|
|
|
@ -263,18 +263,40 @@ 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
|
||||
def test_access_chrome_objects_in_event_listeners(self):
|
||||
# sandbox.window.addEventListener/removeEventListener
|
||||
# is used by Marionette for installing the unloadHandler which
|
||||
# is used to return an error when a document is unloaded during
|
||||
# script execution.
|
||||
#
|
||||
# Certain web frameworks, notably Angular, override
|
||||
# window.addEventListener/removeEventListener and introspects
|
||||
# objects passed to them. If these objects originates from chrome
|
||||
# without having been cloned, a permission denied error is thrown
|
||||
# as part of the security precautions put in place by the sandbox.
|
||||
|
||||
# addEventListener is called when script is injected
|
||||
self.marionette.navigate(inline("""
|
||||
<script>
|
||||
window.addEventListener = (type, handler) => handler.toString();
|
||||
</script>"""))
|
||||
window.addEventListener = (event, listener) => listener.toString();
|
||||
</script>
|
||||
"""))
|
||||
self.marionette.execute_script("", sandbox=None)
|
||||
|
||||
# removeEventListener is called when sandbox is unloaded
|
||||
self.marionette.navigate(inline("""
|
||||
<script>
|
||||
window.removeEventListener = (event, listener) => listener.toString();
|
||||
</script>
|
||||
"""))
|
||||
self.marionette.execute_script("", sandbox=None)
|
||||
|
||||
def test_access_global_objects_from_chrome(self):
|
||||
# test inspection of arguments
|
||||
self.marionette.execute_script("__webDriverArguments.toString()")
|
||||
|
||||
|
||||
|
||||
class TestExecuteChrome(WindowManagerMixin, TestExecuteContent):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -333,6 +355,9 @@ class TestExecuteChrome(WindowManagerMixin, TestExecuteContent):
|
|||
def test_privileged_code_inspection(self):
|
||||
pass
|
||||
|
||||
def test_access_chrome_objects_in_event_listeners(self):
|
||||
pass
|
||||
|
||||
|
||||
class TestElementCollections(MarionetteTestCase):
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче