Tighten restrictions on hosted apps calling extension APIs
Only allow component apps to make any API calls, and for them only allow the namespaces they explicitly have permission for (plus chrome.test - I need to see if I can rework some WebStore tests to remove even this).
BUG=172369
Review URL: https://chromiumcodereview.appspot.com/12095095
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@180426 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index 3f34ed9..00a1f39e 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -322,6 +322,33 @@
return true;
}
+namespace {
+
+// Only COMPONENT hosted apps may call extension APIs, and they are limited
+// to just the permissions they explicitly request. They should not have access
+// to extension APIs like eg chrome.runtime, chrome.windows, etc. that normally
+// are available without permission.
+// TODO(asargent/kalman) - get rid of this when the features system can express
+// the "non permission" permissions.
+bool AllowHostedAppAPICall(const Extension& extension,
+ const GURL& source_url,
+ const std::string& function_name) {
+ if (extension.location() != extensions::Manifest::COMPONENT)
+ return false;
+
+ if (!extension.web_extent().MatchesURL(source_url))
+ return false;
+
+ // We just allow the hosted app's explicit permissions, plus chrome.test.
+ scoped_refptr<const extensions::PermissionSet> permissions =
+ extension.GetActivePermissions();
+ return (permissions->HasAccessToFunction(function_name, false) ||
+ StartsWithASCII(function_name, "test.", true /*case_sensitive*/));
+}
+
+} // namespace
+
+
// static
ExtensionFunction* ExtensionFunctionDispatcher::CreateExtensionFunction(
const ExtensionHostMsg_Request_Params& params,
@@ -339,10 +366,20 @@
return NULL;
}
- if (api->IsPrivileged(params.name) &&
- !process_map.Contains(extension->id(), requesting_process_id)) {
- LOG(ERROR) << "Extension API called from incorrect process "
- << requesting_process_id
+ // Most hosted apps can't call APIs.
+ bool allowed = true;
+ if (extension->is_hosted_app())
+ allowed = AllowHostedAppAPICall(*extension, params.source_url,
+ params.name);
+
+ // Privileged APIs can only be called from the process the extension
+ // is running in.
+ if (allowed && api->IsPrivileged(params.name))
+ allowed = process_map.Contains(extension->id(), requesting_process_id);
+
+ if (!allowed) {
+ LOG(ERROR) << "Extension API call disallowed - name:" << params.name
+ << " pid:" << requesting_process_id
<< " from URL " << params.source_url.spec();
SendAccessDenied(ipc_sender, routing_id, params.request_id);
return NULL;