Improve extension security
Improving security in Manifest V3
This is the last of three sections describing changes needed for code that is not part of the extension service worker. It describes changes required to improve the security of extensions. The other two sections cover updating your code needed for upgrading to Manifest V3 and replacing blocking web requests.
Remove execution of arbitrary strings
You can no longer 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 resources from the extension bundle.
- Use
chrome.runtime.getURL()
to build resource URLs at runtime.
The executeScript()
method is now in the scripting
namespace rather than the tabs
namespace. For information on updating calls, see Move executeScript().
Remove remotely hosted code
In Manifest V3, all of your extension's logic must be part of the extension package. You can no longer load and execute remotely hosted files. Examples include:
- JavaScript files pulled from the developer's server.
- Any library hosted on a [CDN][mdn-cdn].
Alternative approaches are available, depending on your use case and the reason for remote hosting. Here are approaches to consider:
- 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.
- Externalized logic with a remote service
- Your extension calls a remote web service. This lets you keep code private and change it as needed while avoiding the extra overhead of resubmitting to the Chrome Web Store.
- Bundle third-party libraries
- Your extension includes minified files. Popular frameworks such as React and Bootstrap have minified versions available for download. Include them in your bundle and reference them as you would any other script. For example:
<script src="./react-dom.production.min.js"></script>
<link href="./bootstrap.min.css" rel="stylesheet">
To include a library in a service worker set the "background.type"
to "module"
in the manifest and use an import
statement.
Use external libraries in tab-injected scripts
External libraries may no longer be loaded remotely. They must be part of your extension bundle. Load them at runtime by adding them to the files
array when calling executeScript()
. You can still load data remotely at runtime.
chrome.scripting.executeScript({
target: {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}!')`
});
Manifest V3
async function getCurrentTab() {/* ... */}
let tab = await getCurrentTab();
function showAlert(givenName) {
alert(`Hello, ${givenName}`);
}
let name = 'World';
chrome.scripting.executeScript({
target: {tabId: tab.id},
func: showAlert,
args: [name],
});
The Chrome Extension Samples repo contains a function injection example you can step through. An example of getCurrentTab()
is in the reference for that function.
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 supports two properties: "extension_pages"
and "sandbox"
.
Manifest V2
{
...
"content_security_policy": "default-src 'self'"
...
}
Manifest V3
{
...
"content_security_policy": {
"extension_pages": "default-src 'self'",
"sandbox": "..."
}
...
}
extension_pages
: Refers to contexts in your extension, including html files and service workers.
These page types are served from the chrome-extension://
protocol. For instance, a page in your extension is chrome-extension://EXTENSION_ID/foo.html
.
sandbox
: Refers to any sandboxed extension pages that your extension uses.
Remove unsupported content security policies
Manifest V3 disallows certain content security policy values in the "extension_pages"
field that were allowed in Manifest V2. Specifically Manifest V3 disallows those that allow remote code execution. The script-src,
object-src
, and worker-src
directives may only have the following values:
self
none
wasm-unsafe-eval
- Unpacked 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.