Extension Permissions are used to determine which capabilities are exposed to a given extension. They are specified in the extension’s manifest.json file.
This document describes the internal implementation of extension permissions. For more general extension permission information, see the public documentation on declaring permissions and permission warnings.
There are three basic classes of permissions.
API permissions are typically used to grant an extension access to a specific API. These are usually specified by a reserved string (like the API name). Examples include
storage, and others.
Match patterns provide access to a set of urls. Match patterns can encompass multiple hosts, so a single pattern may provide access to many different domains (or even, every domain). For more information, see the public match pattern documentation. In the codebase, match patterns are implemented as URLPattern.
Explicit host permissions are match patterns specified in the
permissions key of the extension’s manifest. These patterns control access to APIs that read or modify host data, such as
Note: Any path component is currently ignored for explicit hosts in permissions parsing.
Scriptable hosts are match patterns used in the content_scripts entry of the extension’s manifest. These only control which sites an extension can use content scripts on, and do not affect any other API.
From a messaging standpoint, we treat both explicit hosts and scriptable hosts the same (with each allowing the extension to read and modify data on one or more domains). The distinction is only to provide granular permissions in order to restrict what we provide the extension.
A manifest permission is a specified manifest entry that provides an extension with some permission. Examples of this include page overrides (to allow extensions to override a page, like the New Tab Page), externally_connectable (allowing extensions to communicate with websites or extensions), and bluetooth (allowing the extension to communicate with specific bluetooth devices). Manifest permissions are effectively similar to API permissions in that they provide access to a certain capability. From an implementation standpoint, permissions can often be implemented as either an API Permission or a Manifest Permission. For the rest of this document, we group both API and manifest permissions into “API permissions”.
Permissions are stored in the Preferences file, under the extension’s entry. We store two different sets of permissions: granted permissions and active permissions. Note that neither of these include any non-persistent permissions.
Granted permissions are the permissions that the extension has ever been granted by the user (and have not been revoked by the user). When the user installs an extension, we grant the accepted permissions. If the extension is granted more permissions at any point, we update the set of granted permissions to include those. Extensions can be granted additional permissions through either an extension update that requires new permissions (assuming the user agrees) or through the permissions API (which is used for optional permissions). Granted permissions can be thought of as the maximum level of permissions an extension may have.
Active permissions are the permissions that an extension currently has. This set is used to initialize extension permission state when the extension is loaded, and determines the APIs and domains an extension can access.
The sets of active permissions and granted permissions can differ in a few scenarios.
chrome.permissions.request()), the user is prompted to accept or refuse it. If the user accepts, the permission is added to both the active and granted permissions. The extension can then remove this permission using
chrome.permissions.remove(). Removing the permission removes it from the active permissions (reducing the extension’s immediate capabilities), but does not remove it from the granted permissions. If the extension uses
chrome.permissions.request()for the same permission after removing it, the user will not be prompted again because the permission is present in the granted permissions.
Some permissions are granted ephemerally, and are not stored or persisted. These are tab-specific permissions in the code, and are used with the
activeTab permission. This provides the extension with temporary access to a tab, so that it can use
webRequest API, see the tab's URL and favicon with the
tabs API, and capture the screen with the
chrome.tabs.captureTab() function. When the user closes or navigates the tab, the permission is revoked.
When an extension is updated to a new version, the new version can include new permissions. Chrome will disable the extension if it is detected that the new version contains higher privilege than what is currently granted to the extension (see also Determining Privilege Increase). Note that this compares the new set of requested permissions to the granted permissions, rather than the active permissions for the extension. This distinction is important when the granted set is different than the active set. Consider the two following cases:
Most permissions have an associated warning string, which describes what the permission allows the extension to do. Permission warnings are shown to the user at a number of different times:
In order to maximize the benefit to users, Chrome tries to show as few warnings as possible, while ensuring they are still accurate.
Some permissions (like the
storage API) are considered relatively harmless, and will not generate a permission warning.
Certain permissions “contain” or imply other permissions. With host permissions, this is easy to understand: if an extension has access to all google.com sites (i.e.,
*://*.google.com/*), requesting access to a specific google.com site (
https://maps.google.com/*) is redundant. We should not warn the user that the extension wants to both “access all google.com sites” and “access maps.google.com”.
API permissions can be similarly redundant, if one API provides the same or more privilege than another. For instance, if an extension has access to a user’s history, then it implicitly has access to the user’s top sites. Thus, if an extension requests both the
history permission and the
topSites permission, we will only display a single warning to the user.
Not all permission changes result in disabling the extension. In order to calculate if an extension has escalated privilege and should be disabled, Chrome compares the permission messages that are associated with the granted permissions and the newly-requested permissions. This is different than comparing the permissions themselves because of messageless permissions and permission collapsing.
This has implications when determining privilege increase. If an extension adds new permissions but all of those permissions are either a) messageless or b) collapsed into already-granted permissions, then the extension is not disabled. Otherwise, Chrome considers it a privilege increase, disables the extension, and notifies the user (allowing them to accept the new permissions and re-enable it, if they want).
Note: since optional permissions are not granted automatically, adding optional permissions in a new version will never disable the extension.
Granted permissions are not currently synced. Instead, we sync the disable reasons for an extension (which can include that an extension was disabled for a permissions increase) and the extension version. In most cases, this allows users to approve an extension only once and have it enabled on all devices. When the extension is updated to a new version, if it has increased permissions, it will be disabled on the device. The user can then approve the new permissions, which enables the extension. When the user goes to a new device, the extension will be updated, and Chrome will notice the increased permissions, but since the extension has been approved in sync, it will not be disabled.
There are two known issues related to syncing extensions: