Skip to content

Commit

Permalink
Fix inaccuracies in extension CSP documentation (mdn#20437)
Browse files Browse the repository at this point in the history
- Document content script CSP ( bugzil.la/1581611 ).
- Clarify what CSP covers (not just `<script>`).
- Clarify role of object-src ( bugzil.la/1766881 , crbug.com/1320785 ).
- Clarify what is considered a secure source for MV2 and MV3.
- Remove localhost ( bugzil.la/1789751 ).
- Remove "valid" examples that are actually not valid MV3 examples.
- Add formatting to style invalid examples as "example-bad".
  • Loading branch information
Rob--W authored and Himanshu Garg committed Sep 27, 2022
1 parent a478aca commit 7065975
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ tags:

{{AddonSidebar}}

Extensions developed with WebExtension APIs have a Content Security Policy (CSP) applied to them by default. This restricts the sources from which they can load [\<script>](/en-US/docs/Web/HTML/Element/script) and [\<object>](/en-US/docs/Web/HTML/Element/object) resources, and disallows potentially unsafe practices such as the use of [`eval()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval). This article explains briefly what a CSP is, what the default policy is and what it means for an extension, and how an extension can change the default CSP.
Extensions developed with WebExtension APIs have a Content Security Policy (CSP) applied to them by default. This restricts the sources from which they can load code such as [\<script>](/en-US/docs/Web/HTML/Element/script) and disallows potentially unsafe practices such as using [`eval()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval). This article briefly explains what a CSP is, what the default policy is and what it means for an extension, and how an extension can change the default CSP.

[Content Security Policy](/en-US/docs/Web/HTTP/CSP) (CSP) is a mechanism to help prevent websites from inadvertently executing malicious content. A website specifies a CSP using an HTTP header sent from the server. The CSP is mostly concerned with specifying legitimate sources of various types of content, such as scripts or embedded plugins. For example, a website can use it to specify that the browser should only execute JavaScript served from the website itself, and not from any other sources. A CSP can also instruct the browser to disallow potentially unsafe practices, such as the use of [`eval()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval).

Expand Down Expand Up @@ -58,15 +58,17 @@ These policies are applied to any extension that has not explicitly set its own

### Location of script and object resources

Under the default CSP you may only load [\<script>](/en-US/docs/Web/HTML/Element/script) and [\<object>](/en-US/docs/Web/HTML/Element/object) resources that are local to the extension. For example, consider a line like this in an extension's document:
Under the default CSP, you can only load code that is local to the extension. The CSP limits {{CSP("script-src")}} to secure sources only, which covers [\<script>](/en-US/docs/Web/HTML/Element/script) resources, [ES6 modules](/en-US/docs/Web/JavaScript/Guide/Modules) and [web workers](/en-US/docs/Web/API/Web_Workers_API/Using_web_workers). In browsers that support obsolete [plugins](/en-US/docs/Glossary/Plugin), the {{CSP("object-src")}} directive is also restricted. For more information on object-src in extensions, see the WECG issue [Remove object-src from the CSP (at least in MV3)](https://github.com/w3c/webextensions/issues/204)).

For example, consider a line like this in an extension's document:

```html
<script src="https://code.jquery.com/jquery-2.2.4.js"></script>
```

This doesn't load the requested resource: it fails silently, and any object that you expect to be present from the resource is not found. There are two main solutions to this:

- download the resource, package it in your extension, and refer to this version of the resource
- download the resource, package it in your extension, and refer to this version of the resource.
- allow the remote origin you need using the [`content_security_policy`](/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/content_security_policy) key or, in Manifest V3, the `content_scripts` property.

### eval() and friends
Expand Down Expand Up @@ -110,3 +112,12 @@ From Firefox 102 and Chrome 103, `'wasm-unsafe-eval'` can be included in the [`c
Manifest V2 extensions in Firefox can use WebAssembly without `'wasm-unsafe-eval'` in their CSP for backward compatibility. However, this behavior isn't guaranteed, see {{bug(1770909)}}. Extensions using WebAssembly are therefore encouraged to declare `'wasm-unsafe-eval'` in their CSP.

For Chrome, extensions cannot use WebAssembly in version 101 or earlier. In 102, extensions can use WebAssembly (the same behavior as Firefox 101 and earlier). From version 103, extensions can use WebAssembly if they include `'wasm-unsafe-eval'` in the `content_security_policy` in the manifest key.

## CSP for content scripts

In Manifest V2, content scripts have no CSP.
As of Manifest V3, content scripts share the default CSP as extensions. It is currently not possible to specify a separate CSP for content scripts ([source](https://bugzilla.mozilla.org/show_bug.cgi?id=1581611#c10)).

The extent to which the CSP controls loads from content scripts varies by browser.
In Firefox, JavaScript features such as eval are restricted by the extension CSP. Generally, most DOM-based APIs are subjected to the CSP of the web page.
In Chrome, many DOM APIs are covered by the extension CSP instead of the web page's CSP ([crbug 896041](https://bugs.chromium.org/p/chromium/issues/detail?id=896041)).
Original file line number Diff line number Diff line change
Expand Up @@ -27,35 +27,48 @@ browser-compat: webextensions.manifest.content_security_policy
<tr>
<th scope="row">Example</th>
<td>
Manifest V2:
<pre class="brush: json">
"content_security_policy": "default-src 'self'"</pre
>
"content_security_policy": "default-src 'self'"</pre>
Manifest V3:
<pre class="brush: json">
"content_security_policy": {
"extension_pages": "default-src 'self'"
}</pre>
</td>
</tr>
</tbody>
</table>

Extensions have a content security policy applied to them by default. The default policy restricts the sources from which they can load [\<script>](/en-US/docs/Web/HTML/Element/script) and [\<object>](/en-US/docs/Web/HTML/Element/object) resources, and disallows potentially unsafe practices such as the use of [`eval()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval). See [Default content security policy](/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_Security_Policy#default_content_security_policy) to learn more about the implications of this.
Extensions have a content security policy applied to them by default. The default policy restricts the sources from which they can load code (such as [\<script>](/en-US/docs/Web/HTML/Element/script) resources), and disallows potentially unsafe practices such as the use of [`eval()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval). See [Default content security policy](/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_Security_Policy#default_content_security_policy) to learn more about the implications of this.

You can use the `"content_security_policy"` manifest key to loosen or tighten the default policy. This key is specified in just the same way as the Content-Security-Policy HTTP header. See [Using Content Security Policy](/en-US/docs/Web/HTTP/CSP) for a general description of CSP syntax.

For example, you can use this key to:

- Allow the extension to load scripts and objects from outside its package, by supplying their URL in the {{CSP("script-src")}} or {{CSP("object-src")}} directives.
- Allow the extension to execute inline scripts, by [supplying the hash of the script in the `script-src` directive](/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#unsafe_inline_script).
- Allow the extension to use `eval()` and similar features, by including `'unsafe-eval'` in the {{CSP("script-src")}} directive.
- Restrict permitted sources for other types of content, such as images and stylesheets, using the appropriate [policy directive](/en-US/docs/Web/HTTP/Headers/Content-Security-Policy).
- Allow the extension to take advantage of [WebAssembly](/en-US/docs/WebAssembly) by including the `'wasm-unsafe-eval'` source in the `script-src` directive.
- Loosen the default default {{CSP("script-src")}} policies (Manifest V2 only):
- Allow the extension to load scripts from outside its package, by supplying their URL in the {{CSP("script-src")}} directive.
- Allow the extension to execute inline scripts, by [supplying the hash of the script in the `script-src` directive](/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#unsafe_inline_script).
- Allow the extension to use `eval()` and similar features, by including `'unsafe-eval'` in the {{CSP("script-src")}} directive.

There are restrictions on the policy you can specify here:

- The policy may include just {{CSP("default-src")}}, but if not the policy must include at least the {{CSP("script-src")}} and the {{CSP("object-src")}} directives, and the {{CSP("script-src")}} directive must contain the keyword `'self'`.
- Directives that reference code – {{CSP("script-src")}}, {{CSP("object-src")}}, {{CSP("worker-src")}}, and {{CSP("default-src")}} – can't specify wildcard hosts, such as `"default-src 'self' *"`. There are no wildcard restrictions on CSP directives that load non-script content, such as {{CSP("img-src")}} – wildcards are a valid content security policy value for regular web pages, so they are a valid value for extensions too.
- The {{CSP("script-src")}} directive must include at least the `'self'` keyword, and may only contain secure sources. The set of permitted secure sources differ between Manifest V2 and Manifest V3.
- The policy may include just {{CSP("default-src")}} (without {{CSP("script-src")}}) if its sources meet the requirement for the {{CSP("script-src")}} directive.
- The {{CSP("object-src")}} keyword may be required in some browsers that support obsolete [plugins](/en-US/docs/Glossary/Plugin). If required, it should be set to a secure source such as `'none'`. This may be required for browsers up until 2022 ([more information](https://github.com/w3c/webextensions/issues/204)).
- Directives that reference code – {{CSP("script-src")}}, {{CSP("script-src-elem")}}, {{CSP("worker-src")}}, and {{CSP("default-src")}} (if used as fallback) share the same secure source requirement. There are no restrictions on CSP directives that cover non-script content, such as {{CSP("img-src")}}.

In Manifest V3, all CSP sources that refer to external or non-static content are forbidden. The only permitted values are `'none'`, `'self'`, and `'wasm-unsafe-eval'`.
In Manifest V2, a source for a script directive is considered secure if it passes the following criteria:

- Wildcard hosts are not permitted, such as `"script-src 'self' *"`.
- Remote sources must use `https:` schemes.
- Remote sources must not use wildcards for any domains in the [public suffix list](https://publicsuffix.org/list/) (so "\*.co.uk" and "\*.blogspot.com" are not allowed, although "\*.foo.blogspot.com" is allowed).
- All sources must specify a host.
- The only permitted schemes for sources are: `blob:`, `filesystem:`, `moz-extension:`, `https:`, and `wss:`.
- The only permitted [keywords](/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/default-src#sources) are: `'none'`, `'self'`, and `'unsafe-eval'`.
- The only permitted [keywords](/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/default-src#sources) are: `'none'`, `'self'`, `'unsafe-eval'`, and `'wasm-unsafe-eval'`.

## Manifest V2 syntax

Expand All @@ -82,11 +95,11 @@ In Manifest V3, the `content_security_policy` key is an object that may have any
<td><code>extension_pages</code></td>
<td><code>String</code></td>
<td>
The content security policy used for extension pages. The <code>script-src</code>, <code>object-src</code>, and <code>worker-src</code> directives may only have these values:
The content security policy used for extension pages. The <code>script-src</code> and <code>worker-src</code> directives may only have these values:
<ul>
<li><code>self</code></li>
<li><code>none</code></li>
<li>Any localhost source, (<code>http://localhost</code>, <code>http://127.0.0.1</code>, or any port on those domains.)</li>
<li><code>'self'</code></li>
<li><code>'none'</code></li>
<li><code>'wasm-unsafe-eval'/code></li>
</ul>
</td>
</tr>
Expand All @@ -107,6 +120,8 @@ In Manifest V3, the `content_security_policy` key is an object that may have any
> **Note:** Valid examples demonstrate the correct use of keys in CSP.
> However, extensions with 'unsafe-eval', remote script, blob, or remote sources in their CSP are not allowed for Firefox extensions as per the [add-on policies](https://extensionworkshop.com/documentation/publish/add-on-policies/) and due to major security issues.
> **Note:** The examples below include the {{CSP("script-src")}} directive because this was required in older browser versions. This directive is optional in modern browsers without obsolete [plugins](/en-US/docs/Glossary/Plugin) ([more information](https://github.com/w3c/webextensions/issues/204)).
Require that all types of content should be packaged with the extension:

- Manifest V2
Expand All @@ -125,19 +140,13 @@ Require that all types of content should be packaged with the extension:

Allow remote scripts from "https://example.com":

- Manifest V2:
- Manifest V2

```json
"content_security_policy": "script-src 'self' https://example.com; object-src 'self'"
```

- Manifest V3

```json
"content_security_policy": {
"extension_pages": "script-src 'self' https://example.com; object-src 'self'"
}
```
- Manifest V3 does not allow remote URLs in `script-src` of `extension_pages`.

Allow remote scripts from any subdomain of "jquery.com":

Expand All @@ -147,13 +156,7 @@ Allow remote scripts from any subdomain of "jquery.com":
"content_security_policy": "script-src 'self' https://*.jquery.com; object-src 'self'"
```

- Manifest V3

```json
"content_security_policy": {
"extension_pages": "script-src 'self' https://*.jquery.com; object-src 'self'"
}
```
- Manifest V3 does not allow remote URLs in `script-src` of `extension_pages`.

Allow [`eval()` and friends](/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_Security_Policy#eval%28%29_and_friends):

Expand All @@ -163,13 +166,7 @@ Allow [`eval()` and friends](/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_S
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self';"
```

- Manifest V3

```json
"content_security_policy": {
"extension_pages": "script-src 'self' 'unsafe-eval'; object-src 'self';"
}
```
- Manifest V3 does not allow `'unsafe-eval'` in `script-src`.

Allow the inline script: `"<script>alert('Hello, world.');</script>"`:

Expand All @@ -179,13 +176,7 @@ Allow the inline script: `"<script>alert('Hello, world.');</script>"`:
"content_security_policy": "script-src 'self' 'sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng='; object-src 'self'"
```

- Manifest V3

```json
"content_security_policy": {
"extension_pages": "script-src 'self' 'sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng='; object-src 'self'"
}
```
- Manifest V3 does not allow CSP hashes in `script-src` of `extension_pages`.

Keep the rest of the policy, but also require that images should be packaged with the extension:

Expand All @@ -207,7 +198,7 @@ Enable the use of [WebAssembly](/en-US/docs/WebAssembly):

- Manifest V2

For backward compatibility, Manifest V2 extensions can use WebAssembly without the use of `'wasm-unsafe-eval'`. However, if the extension uses WebAssembly, the inclusion of `'wasm-unsafe-eval'` is recommended. See [WebAssembly](/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_Security_Policy#webassembly) on the Content Security Policy page for more information.
For backward compatibility, Manifest V2 extensions in Firefox can use WebAssembly without the use of `'wasm-unsafe-eval'`. However, this behavior isn't guaranteed, see {{bug(1770909)}}. Extensions using WebAssembly are therefore encouraged to declare `'wasm-unsafe-eval'` in their CSP. See [WebAssembly](/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_Security_Policy#webassembly) on the Content Security Policy page for more information.

```json
"content_security_policy": "script-src 'self' 'wasm-unsafe-eval'"
Expand All @@ -223,39 +214,39 @@ Enable the use of [WebAssembly](/en-US/docs/WebAssembly):

### Invalid examples

Policy that omits the `"object-src"` directive:
Policy that omits the `"object-src"` directive (only invalid in browsers that support obsolete [plugins](/en-US/docs/Glossary/Plugin); [more information](https://github.com/w3c/webextensions/issues/204)):

```json
```json example-bad
"content_security_policy": "script-src 'self' https://*.jquery.com;"
```

Policy that omits the `"self"` keyword in the `"script-src"` directive:

```json
```json example-bad
"content_security_policy": "script-src https://*.jquery.com; object-src 'self'"
```

Scheme for a remote source is not `https`:

```json
```json example-bad
"content_security_policy": "script-src 'self' http://code.jquery.com; object-src 'self'"
```

Wildcard is used with a generic domain:

```json
```json example-bad
"content_security_policy": "script-src 'self' https://*.blogspot.com; object-src 'self'"
```

Source specifies a scheme but no host:

```json
```json example-bad
"content_security_policy": "script-src 'self' https:; object-src 'self'"
```

Directive includes the unsupported keyword `'unsafe-inline'`:

```json
```json example-bad
"content_security_policy": "script-src 'self' 'unsafe-inline'; object-src 'self'"
```

Expand Down

0 comments on commit 7065975

Please sign in to comment.