Bug 1330340 - Check host permissions for webRequest listeners draft
authorTomislav Jovanovic <tomica@gmail.com>
Mon, 30 Jan 2017 19:45:20 +0100
changeset 468132 4b14ab75b19d4ad39611c567aee3c1cfcfe93484
parent 467834 71224049c0b52ab190564d3ea0eab089a159a4cf
child 543859 88bb469b2270fd4bbf9d5c03dedfa9725d66aa24
push id43365
push userbmo:tomica@gmail.com
push dateMon, 30 Jan 2017 19:50:19 +0000
bugs1330340
milestone54.0a1
Bug 1330340 - Check host permissions for webRequest listeners MozReview-Commit-ID: FoTuPfPrajM
toolkit/components/extensions/ext-webRequest.js
toolkit/components/extensions/test/mochitest/file_image_great.png
toolkit/components/extensions/test/mochitest/file_with_images.html
toolkit/components/extensions/test/mochitest/mochitest-common.ini
toolkit/components/extensions/test/mochitest/test_ext_webrequest_background_events.html
toolkit/components/extensions/test/mochitest/test_ext_webrequest_hosts_permissions.html
toolkit/components/extensions/test/mochitest/test_ext_webrequest_suspend.html
toolkit/modules/addons/WebRequest.jsm
--- a/toolkit/components/extensions/ext-webRequest.js
+++ b/toolkit/components/extensions/ext-webRequest.js
@@ -22,16 +22,24 @@ function WebRequestEventManager(context,
   let name = `webRequest.${eventName}`;
   let register = (fire, filter, info) => {
     let listener = data => {
       // Prevent listening in on requests originating from system principal to
       // prevent tinkering with OCSP, app and addon updates, etc.
       if (data.isSystemPrincipal) {
         return;
       }
+      const hosts = context.extension.whiteListedHosts;
+      // Check hosts permissions for both the resource being
+      // requested, and the origin that initiated the request.
+      if (!hosts.matchesIgnoringPath(NetUtil.newURI(data.url)) ||
+          data.originUrl && !hosts.matchesIgnoringPath(NetUtil.newURI(data.originUrl))) {
+        return;
+      }
+
       let browserData = {};
       extensions.emit("fill-browser-data", data.browser, browserData);
       if (filter.tabId != null && browserData.tabId != filter.tabId) {
         return;
       }
       if (filter.windowId != null && browserData.windowId != filter.windowId) {
         return;
       }
new file mode 100644
index 0000000000000000000000000000000000000000..769c636340e11f9d2a0b7eb6a84d574dd9563f0c
GIT binary patch
literal 580
zc$@)50=xZ*P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz)=5M`RCwBA
z{Qv(y10?_;fS8au@87>?@9gaSt*os4-<6T^zln*-e<1(Y>eZ{a-@A8D7MlS80mJ}u
z0SKQtbH>fs*!aH-1H=C_K)ecw?*efe5W7I}s#U9Y!PLVrKmdV>nKNfT1{(H16si$K
zmjm&CV+al6D=8`c7X*o+82}JK4A3z64>JJB_`e(E3S)?2<zN>X{|^lf1sei(+1<Me
zFarPr2&}oIqvIC?)OL^o?-&p^!wh-{#k-;2f_VoZfS{%bLi}zFF<>UtAY{W<LBj?n
zz6$CsfB=HI;P*^44eyZn#$YcBg1rF~2L~`P&;bI75#$0;v@zVf$It;Z4d`qJS0Dzu
zh@l)BQx!mb7Roj*FK2kaXAgtR*|Q9LfP8=e0=od{pY0$UI-sVXf!f>w#jt?wfcn3@
zy!=0d5|Evi_8%aC7~Z{m#}1AKK|~<_M{=g1px}QcP=ErR57Iaj7$e5OumVLr$n^jL
z1djz!sJcLHd57c@W2lWFi_p^m2m=HVoB>kgf@C|$pqa*ykjAAMgaHBwo)>`0c=vmt
z+g3yQpuk*x7A(#H^u|wInF%0(FiZq_r2`t3pnwGh6fWCA7$ATcDb3CR0R{jJCzQv)
SYsoAC0000<MNUMnLSTYrIq9PS
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/mochitest/file_with_images.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<html>
+<head>
+  <meta charset="utf-8">
+</head>
+<body>
+  <img src="https://example.com/tests/toolkit/components/extensions/test/mochitest/file_image_good.png">
+  <img src="http://mochi.test:8888/tests/toolkit/components/extensions/test/mochitest/file_image_great.png">
+</body>
+</html>
--- a/toolkit/components/extensions/test/mochitest/mochitest-common.ini
+++ b/toolkit/components/extensions/test/mochitest/mochitest-common.ini
@@ -14,17 +14,19 @@ support-files =
   file_webNavigation_frameRedirect.html
   file_webNavigation_manualSubframe.html
   file_webNavigation_manualSubframe_page1.html
   file_webNavigation_manualSubframe_page2.html
   file_WebNavigation_page1.html
   file_WebNavigation_page2.html
   file_WebNavigation_page3.html
   file_with_about_blank.html
+  file_with_images.html
   file_image_good.png
+  file_image_great.png
   file_image_bad.png
   file_image_redirect.png
   file_style_good.css
   file_style_bad.css
   file_style_redirect.css
   file_script_good.js
   file_script_bad.js
   file_script_redirect.js
@@ -102,16 +104,18 @@ skip-if = (os == 'android') # Bug 125897
 [test_ext_webrequest_auth.html]
 skip-if = os == 'android' # webrequest api unsupported (bug 1258975).
 [test_ext_webrequest_background_events.html]
 skip-if = os == 'android' # webrequest api unsupported (bug 1258975).
 [test_ext_webrequest_basic.html]
 skip-if = os == 'android' # webrequest api unsupported (bug 1258975).
 [test_ext_webrequest_filter.html]
 skip-if = os == 'android' # webrequest api unsupported (bug 1258975).
+[test_ext_webrequest_hosts_permissions.html]
+skip-if = os == 'android' # webrequest api unsupported (bug 1258975).
 [test_ext_webrequest_suspend.html]
 skip-if = os == 'android' # webrequest api unsupported (bug 1258975).
 [test_ext_webrequest_upload.html]
 skip-if = os == 'android' # webrequest api unsupported (bug 1258975).
 [test_ext_webnavigation.html]
 skip-if = os == 'android' # port.sender.tab is undefined on Android (bug 1258975).
 [test_ext_webnavigation_filters.html]
 skip-if = os == 'android' # port.sender.tab is undefined on Android (bug 1258975).
--- a/toolkit/components/extensions/test/mochitest/test_ext_webrequest_background_events.html
+++ b/toolkit/components/extensions/test/mochitest/test_ext_webrequest_background_events.html
@@ -54,16 +54,18 @@ add_task(function* test_webRequest_servi
 
   yield extension.startup();
   let registration = yield navigator.serviceWorker.register("webrequest_worker.js", {scope: "."});
   yield extension.awaitMessage("done");
   yield registration.unregister();
   yield extension.unload();
 });
 
+// Bug 1271354 - Support moz-extension: urls in MatchPattern
+/*
 add_task(function* test_webRequest_background_events() {
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       permissions: [
         "webRequest",
         "<all_urls>",
       ],
     },
@@ -102,12 +104,14 @@ add_task(function* test_webRequest_backg
       });
     },
   });
 
   yield extension.startup();
   yield extension.awaitMessage("done");
   yield extension.unload();
 });
+*/
+
 </script>
 
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/mochitest/test_ext_webrequest_hosts_permissions.html
@@ -0,0 +1,55 @@
+<!doctype html>
+<html>
+<head>
+  <title>Test webRequest checks host permissions</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+
+<script type="text/javascript">
+"use strict";
+
+add_task(function* test_webRequest_host_permissions() {
+  function background() {
+    function png(details) {
+      browser.test.sendMessage("png", details.url);
+    }
+    browser.webRequest.onBeforeRequest.addListener(png, {urls: ["*://*/*.png"]});
+    browser.test.sendMessage("ready");
+  }
+
+  const all = ExtensionTestUtils.loadExtension({background, manifest: {permissions: ["webRequest", "<all_urls>"]}});
+  const example = ExtensionTestUtils.loadExtension({background, manifest: {permissions: ["webRequest", "https://example.com/"]}});
+  const mochi_test = ExtensionTestUtils.loadExtension({background, manifest: {permissions: ["webRequest", "http://mochi.test/"]}});
+
+  yield all.startup();
+  yield example.startup();
+  yield mochi_test.startup();
+
+  yield all.awaitMessage("ready");
+  yield example.awaitMessage("ready");
+  yield mochi_test.awaitMessage("ready");
+
+  const win1 = window.open("https://example.com/tests/toolkit/components/extensions/test/mochitest/file_with_images.html");
+  ok((yield all.awaitMessage("png")).endsWith("good.png"), "<all_urls> permission gets to see good.png");
+  ok((yield example.awaitMessage("png")).endsWith("good.png"), "example permission sees same-origin example.com image");
+  ok((yield all.awaitMessage("png")).endsWith("great.png"), "<all_urls> permission also sees great.png");
+  win1.close();
+
+  const win2 = window.open("http://mochi.test:8888/tests/toolkit/components/extensions/test/mochitest/file_with_images.html");
+  ok((yield all.awaitMessage("png")).endsWith("good.png"), "<all_urls> permission gets to see good.png");
+  ok((yield mochi_test.awaitMessage("png")).endsWith("great.png"), "mochi.test permission sees same-origin mochi.test image");
+  ok((yield all.awaitMessage("png")).endsWith("great.png"), "<all_urls> permission also sees great.png");
+  win2.close();
+
+  yield all.unload();
+  yield example.unload();
+  yield mochi_test.unload();
+});
+
+</script>
+</body>
+</html>
--- a/toolkit/components/extensions/test/mochitest/test_ext_webrequest_suspend.html
+++ b/toolkit/components/extensions/test/mochitest/test_ext_webrequest_suspend.html
@@ -14,16 +14,17 @@
 "use strict";
 
 add_task(function* test_suspend() {
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       permissions: [
         "webRequest",
         "webRequestBlocking",
+        "http://mochi.test/",
       ],
     },
 
     background() {
       browser.webRequest.onBeforeSendHeaders.addListener(
         details => {
           // Make sure that returning undefined or a promise that resolves to
           // undefined does not break later handlers.
@@ -86,16 +87,18 @@ add_task(function* test_error_resume() {
     Services.obs.addObserver(observer, "http-on-modify-request", false);
   });
 
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       permissions: [
         "webRequest",
         "webRequestBlocking",
+        "http://example.com/",
+        "http://mochi.test/",
       ],
     },
 
     background() {
       browser.webRequest.onBeforeSendHeaders.addListener(
         details => {
           browser.test.log(`onBeforeSendHeaders({url: ${details.url}})`);
 
--- a/toolkit/modules/addons/WebRequest.jsm
+++ b/toolkit/modules/addons/WebRequest.jsm
@@ -746,17 +746,17 @@ HttpObserverManager = {
       browser: loadContext && loadContext.topFrameElement,
       type: WebRequestCommon.typeForPolicyType(policyType),
       fromCache: getData(channel).fromCache,
       windowId: 0,
       parentWindowId: 0,
     };
 
     if (loadInfo) {
-      let originPrincipal = loadInfo.triggeringPrincipal;
+      let originPrincipal = loadInfo.loadingPrincipal || loadInfo.triggeringPrincipal;
       if (originPrincipal.URI) {
         data.originUrl = originPrincipal.URI.spec;
       }
 
       // If there is no loadingPrincipal, check that the request is not going to
       // inherit a system principal.  triggeringPrincipal is the context that
       // initiated the load, but is not necessarily the principal that the
       // request results in, only rely on that if no other principal is available.