Extensions have access to special privileges within the browser, making them an appealing target for
attackers. If an extension is compromised, *every* user of that extension becomes vulnerable to
malicious and unwanted intrusion. Keep an extension secure and its users protected by incorporating
these practices.

## Protect developer accounts

Extension code is uploaded and updated through Google accounts. If developers' accounts are
compromised, an attacker could push malicious code directly to all users. Protect these accounts by
enabling [two-factor authentication](https://support.google.com/accounts/answer/185839) , preferably with a [security key](https://support.google.com/accounts/answer/6103523).

### Use appropriate member roles

If your publisher has [multiple members](https://developer.chrome.com/docs/webstore/share-ownership.md.txt), make sure the role granted to each
user is appropriate.

## Never use HTTP

When requesting or sending data, avoid an HTTP connection. Assume that any HTTP connections will
have eavesdroppers or contain modifications. HTTPS should always be preferred, as it has built-in
security circumventing most [man-in-the-middle attacks](https://www.owasp.org/index.php/Man-in-the-middle_attack).

## Request minimal permissions

The Chrome browser limits an extension's access to privileges that have been explicitly requested in
the [manifest](https://developer.chrome.com/docs/extensions/mv3/manifest). Extensions should minimize their permissions by only registering APIs and
websites they depend on.

Limiting an extension's privileges limits what a potential attacker can exploit.

### Cross-origin fetch()

An extension can only use `fetch()` and [`XMLHttpRequest()`](https://developer.chrome.com/docs/extensions/mv3/xhr) to get resources from the
extension and from domains specified in the permissions. Note that calls to both are intercepted by
the [fetch](https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent/handled) handler in the service worker.

```json
{
  "name": "Very Secure Extension",
  "version": "1.0",
  "description": "Example of a Secure Extension",
  "host_permissions": [
    "https://developer.chrome.com/*",
    "https://*.google.com/*"
  ],
  "manifest_version": 3
}
```

This extension in the sample above requests access to anything on developer.chrome.com and subdomains of Google by
listing `"https://developer.chrome.com/*"` and `"https://*.google.com/*"` in the permissions. If the
extension were compromised, it would still only have permission to interact with websites that meet
the [match pattern](https://developer.chrome.com/docs/extensions/mv3/match_patterns). The attacker would only have limited ability to access `"https://user_bank_info.com"`, or
interact with `"https://malicious_website.com"`.

## Limit manifest fields

Including unnecessary keys and permissions in the manifest creates vulnerabilities and makes an extension
more visible. Limit manifest fields to those the extension relies on.

### Externally connectable

Use the [`"externally_connectable"`](https://developer.chrome.com/docs/extensions/mv3/manifest/externally_connectable) field to declare which external extensions and web pages the
extension will exchange information with. Restrict who the extension can externally connect with to
trusted sources.

```json
{
  "name": "Super Safe Extension",
  "externally_connectable": {
    "ids": [
      "iamafriendlyextensionhereisdatas"
    ],
    "matches": [
      "https://developer.chrome.com/*",
      "https://*.google.com/*"
    ],
    "accepts_tls_channel_id": false
  },
  ...
}
```

### Web-accessible resources

Making resources accessible by the web, under the [`"web_accessible_resources"`](https://developer.chrome.com/docs/extensions/mv3/manifest/web_accessible_resources) will make an
extension detectable by websites and attackers.

```json
{
  ...
  "web_accessible_resources": [
    {
      "resources": [ "test1.png", "test2.png" ],
      "matches": [ "https://web-accessible-resources-1.glitch.me/*" ]
    }
  ]
  ...
}
```

The more web accessible resources available, the more avenues a potential attacker can exploit. Keep
these files to a minimum.

## Include an explicit content security policy

Include a [content security policy](https://developer.chrome.com/docs/apps/contentSecurityPolicy.md.txt) for the extension in the manifest to prevent cross-site
scripting attacks. If the extension only loads resources from itself register the following:

```json
{
  "name": "Very Secure Extension",
  "version": "1.0",
  "description": "Example of a Secure Extension",
   "content_security_policy": {
    "extension_pages": "default-src 'self'"
  },
  "manifest_version": 3
}
```

If the extension needs to use web assembly, or increase the restrictions on [sandboxed pages](https://developer.chrome.com/docs/extensions/mv3/sandboxingEval), they can be added:

```json
{
  "name": "Very Secure Extension",
  "version": "1.0",
  "description": "Example of a Secure Extension",
   "content_security_policy": {
    "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self';",
    "sandboxed_pages":"script-src 'self' 'wasm-unsafe-eval'; object-src 'self';"
  },

  "manifest_version": 3
}
```

### Avoid document.write() and innerHTML

While it may be simpler to dynamically create HTML elements with `document.write()` and `innerHTML`,
it leaves the extension, and web pages the extension depends on, open to attackers inserting
malicious scripts. Instead, manually create DOM nodes and use `innerText` to insert dynamic content.

```javascript
function constructDOM() {
  let newTitle = document.createElement('h1');
  newTitle.innerText = host;
  document.appendChild(newTitle);
}
```

## Use content scripts carefully

While [content scripts](https://developer.chrome.com/docs/extensions/mv3/content_scripts) live in an [isolated world](https://developer.chrome.com/docs/extensions/mv3/content_scripts#isolated_world), they are not immune from attacks:

- Content scripts are the only part of an extension that interacts directly with the web page. Because of this, hostile web pages may manipulate parts of the DOM the content script depends on, or exploit surprising web standard behavior, such as [named items](https://html.spec.whatwg.org/#dom-window-nameditem).
- To interact with DOM of web pages, content scripts need to execute in the same renderer process as the web page. This makes content scripts vulnerable to leaking data via side channel attacks (e.g., [Spectre](https://spectreattack.com/)), and to being taken over by an attacker if a malicious web page compromises the renderer process.

Operations using sensitive data (such as a user's private information) or Chrome APIs with access to the browser's functions should be performed in the extensions' service worker.
Avoid accidentally exposing extension privileges to content scripts:

- Assume that [messages from a content script](https://developer.chrome.com/docs/extensions/mv3/messaging#content-scripts-are-less-trustworthy) might have been crafted by an attacker (e.g. [validate and sanitize](https://developer.chrome.com/docs/extensions/develop/security-privacy/stay-secure.md.txt#sanitize) all input and protect your scripts from [cross-site scripting](https://developer.chrome.com/docs/extensions/mv3/messaging#cross-site-scripting)).
- Assume any data sent to the content script might leak to the web page. Do not send sensitive data (e.g. secrets from the extension, data from other web origins, browsing history) to content scripts.
- Limit the scope of privileged actions that can be triggered by content scripts. Do not allow content scripts to [trigger requests to arbitrary URLs](https://developer.chrome.com/docs/extensions/mv3/xhr#xhr-vs-content-scripts) or pass arbitrary arguments to extension APIs (e.g., do not allow passing arbitrary URLs to [`fetch()`](https://developer.mozilla.org/docs/Web/API/Fetch_API) or [`browser.tabs.create()`](https://developer.chrome.com/docs/extensions/reference/tabs#method-create) methods).

## Register and sanitize inputs

Safeguard an extension from malicious scripts by limiting listeners to only what the extension is
expecting, validating the senders of incoming data, and sanitizing all inputs.

An extension should only register for [`runtime.onMessageExternal`](https://developer.chrome.com/docs/extensions/reference/runtime#event-onMessageExternal), if it is expecting
communication from an external website or extension. Always validate that the sender matches a
trusted source.

```javascript
// The ID of an external extension
const kFriendlyExtensionId = "iamafriendlyextensionhereisdatas";

browser.runtime.onMessageExternal.addListener(
  function(request, sender, sendResponse) {
    if (sender.id === kFriendlyExtensionId)
      doSomething();
});
```

Even messages via [runtime.onMessage](https://developer.chrome.com/docs/extensions/reference/runtime#event-onMessage) event from the extension itself should be scrutinized to
ensure the [MessageSender](https://developer.chrome.com/docs/extensions/reference/runtime#type-MessageSender) is not from a compromised [content script](https://developer.chrome.com/docs/extensions/mv3/content_scripts).

```javascript
browser.runtime.onMessage.addListener(function(request, sender, sendResponse) {
  if (request.allowedAction)
    console.log("This is an allowed action.");
});
```