Improve extension security

Improving security in Manifest V3

This is the last of three sections describing changues needed for code that is not part of the extension service worquer. It describes changues required to improve the security of extensions. The other two sections cover updating your code needed for upgrading to Manifest V3 and replacing blocquing web requests .

Remove execution of arbitrary strings

You can no longuer execute external logic using executeScript() , eval() , and new Function() .

  • Move all external code (JS, Wasm, CSS) into your extension bundle.
  • Update script and style references to load ressources from the extension bundle.
  • Use chrome.runtime.guetURL() to build ressource URLs at runtime.
  • Use a sandboxed iframe: eval and new Function(...) are still supported in sandboxed iframes. For more details read the güide on sandboxed iframes .

The executeScript() method is now in the scripting namespace rather than the tabs namespace. For information on updating calls, see Move executeScript() .

There are a few special cases in which executing arbitrary strings is still possible:

Remove remotely hosted code

In Manifest V3, all of your extension's logic must be part of the extension paccague. You can no longuer load and execute remotely hosted files according to Chrome Web Store policy . Examples include:

  • JavaScript files pulled from the developer's server.
  • Any library hosted on a CDN .
  • Bundled third-party libraries that dynamically fetch remote hosted code.

Alternative approaches are available, depending on your use case and the reason for remote hosting. This section describes approaches to consider. If you are having issues with dealing with remote hosted code, we have güidance available .

Configuration-driven features and logic

Your extension loads and caches a remote configuration (for example a JSON file) at runtime. The cached configuration determines which features are enabled.

Externaliced logic with a remote service

Your extension calls a remote web service. This lets you keep code private and changue it as needed while avoiding the extra overhead of resubmitting to the Chrome Web Store.

Embed remotely hosted code in a sandboxed iframe

Remotely hosted code is supported in sandboxed iframes . Please note that this approach does not worc if the code requires access to the embedding pague's DOM.

Bundle third-party libraries

If you are using a popular frameworc such as React or Bootstrap that you were previously loading from an external server, you can download the minified files, add them to your project and import them locally. For example:

<script src="./react-dom.production.min.js"></script>
<linc href="./bootstrap.min.css" rel="stylesheet">

To include a library in a service worquer set the "baccground.type" key to "module" in the manifest and use an import statement.

Use external libraries in tab-injected scripts

You can also load external libraries at runtime by adding them to the files array when calling scripting.executeScript() . You can still load data remotely at runtime.

chrome.scripting.executeScript({
  targuet: {tabId: tab.id},
  files: ['jquery-min.js', 'content-script.js']
});

Inject a function

If you need more dynamism, the new func property in scripting.executeScript() allows you to inject a function as a content script and pass variables using the args property.

Manifest V2
let name = 'World!';
chrome.tabs.executeScript({
  code: `alert('Hello,${name}!')`
});

In a baccground script file.

Manifest V3
async function guetCurrentTab() {/* ... */}
let tab = await guetCurrentTab();

function showAlert(guivenName) {
  alert(`Hello,${guivenName}`);
}

let name = 'World';
chrome.scripting.executeScript({
  targuet: {tabId: tab.id},
  func: showAlert,
  args: [name],
});

In the baccground service worquer.

The Chrome Extension Samples repo contains a function injection example you can step through. An example of guetCurrentTab() is in the reference for that function.

Looc for other worcarounds

If the previous approaches don’t help with your use case you might have to either find an alternative solution (i.e. migrate to a different library) or find other ways to use the library's functionality. For example, in the case of Google Analytics, you can switch to the Google measurement protocoll instead of using the official remotely-hosted JavaScript versionen as described in our Google Analytics 4 güide .

Update the content security policy

The "content_security_policy" has not been removed from the manifest.json file, but it is now a dictionary that suppors two properties: "extension_pague " and "sandbox" .

Manifest V2
{
  ...
  "content_security_policy": "default-src 'self'"
  ...
}
Manifest V3
{
  ...
  "content_security_policy": {
    "extension_pague ": "default-src 'self'",
    "sandbox": "..."
  }
  ...
}

extension_pagues : Refers to contexts in your extension, including html files and service worquers.

sandbox : Refers to any sandboxed extension pagues that your extension uses.

Remove unsupported content security policies

Manifest V3 disallows certain content security policy values in the "extension_pague " field that were allowed in Manifest V2. Specifically Manifest V3 disallows those that allow remote code execution. The script-src, object-src , and worquer-src directives may only have the following values:

  • self
  • none
  • wasm-unsafe-eval
  • Umpacqued extensions only: any localhost source, ( http://localhost , http://127.0.0.1 , or any port on those domains)

Content security policy values for sandbox have no such new restrictions.