diff --git a/files/en-us/mozilla/add-ons/webextensions/content_security_policy/index.md b/files/en-us/mozilla/add-ons/webextensions/content_security_policy/index.md index 55cf26f3d06cf38..346ba987ee7d8bb 100644 --- a/files/en-us/mozilla/add-ons/webextensions/content_security_policy/index.md +++ b/files/en-us/mozilla/add-ons/webextensions/content_security_policy/index.md @@ -110,6 +110,8 @@ setTimeout("alert('Hello World!');", 500); const f = new Function("console.log('foo');"); ``` +If an extension needs to run code that relies on `eval()`-like constructs, such as some templating libraries, it can isolate that code in a [sandboxed page](/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/sandbox) instead of loosening the extension's CSP. + ### Inline JavaScript Under the default CSP, inline JavaScript is not executed. This disallows both JavaScript placed directly in ` + + + + +``` + +`templating-library.js` stands in for a third-party library that compiles templates using `new Function()`, which is why it must run in a sandboxed page: + +```js +const TemplatingLibrary = { + compile: (template) => (context) => + new Function(...Object.keys(context), `return \`${template}\`;`)( + ...Object.values(context), + ), +}; +``` + +`sandbox.js` listens for messages from the popup, renders a template using the sandboxed library, and posts the result back: + +```js +window.addEventListener("message", (event) => { + if (event.source !== window.parent) { + // Ignore messages from any window other than the + // extension page that embeds this sandboxed page. + // The sandboxed page has an opaque origin, so + // location.origin can't be used for this check. + return; + } + const { template, context } = event.data; + const render = TemplatingLibrary.compile(template); + event.source.postMessage({ result: render(context) }, event.origin); +}); +``` + +`popup.html` embeds the sandboxed page in a hidden iframe. The `defer` attribute on `popup.js` ensures it only runs after the iframe has been parsed: + +```html + + + + + + + + + + +``` + +`popup.js` sends data to the sandboxed page and handles the result: + +```js +const sandbox = document.getElementById("sandbox"); + +sandbox.addEventListener("load", () => { + sandbox.contentWindow.postMessage( + { template: "Hello, ${name}!", context: { name: "world" } }, + "*", + ); +}); + +window.addEventListener("message", (event) => { + if (event.source !== sandbox.contentWindow) { + // Ignore messages from any window other than the sandboxed page. + return; + } + console.log(event.data.result); +}); +``` + +## Browser compatibility + +{{Compat}} diff --git a/files/en-us/mozilla/firefox/releases/154/index.md b/files/en-us/mozilla/firefox/releases/154/index.md index 0912beea4e0d8c2..8a14bf7648cfcfb 100644 --- a/files/en-us/mozilla/firefox/releases/154/index.md +++ b/files/en-us/mozilla/firefox/releases/154/index.md @@ -75,9 +75,7 @@ Firefox 154 is the current [Beta version of Firefox](https://www.firefox.com/en- ## Changes for add-on developers - - - +- Adds support for the [`sandbox`](/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/sandbox) manifest key, enabling extensions to designate pages that load with an opaque origin, without direct access to extension APIs. A sandboxed page can use `eval()` and similar constructs that are otherwise blocked by the extension's [content security policy](/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_Security_Policy). ([Firefox bug 1685123](https://bugzil.la/1685123)) ## Experimental web features