Sandbox Pages
Sandbox Pages are special extension pages with a different set of CSP restrictions. For example, it is possible to eval
arbitrary code inside a sandbox page. Use the sandbox page to dynamically run code in a secure context with more privileges compared to an extension page.
A sandbox page can mount UI components similar to a CSUI or execute simple scripts. The following example showcases the ability to eval
arbitrary code from a sandbox page and communicate the result back to the caller via message passing.
First, we want to add a sandbox page:
- Create a
sandbox.ts
file or asandboxes/<name>.ts
file in the source directory (project root orsrc
) - Export the following script:
export const life = 42
window.addEventListener("message", async function (event) {
const source = event.source as {
window: WindowProxy
}
source.window.postMessage(eval(event.data), event.origin)
})
The script above listens to a message
event from the window scope, and evals the code sent by the caller via the data property. The sandbox page is now available under sandbox.html
OR sandboxes/<name>.html
in the extension bundle. To send messages to this page, we will need to mount it inside an iframe, and invoke the postMessage API. Let's do so in a popup.tsx
extension page:
import { useEffect, useRef, useState } from "react"
function IndexPopup() {
const iframeRef = useRef<HTMLIFrameElement>(null)
useEffect(() => {
window.addEventListener("message", (event) => {
console.log("EVAL output: " + event.data)
})
}, [])
return (
<div
style={{
display: "flex",
flexDirection: "column",
padding: 16
}}>
<button
onClick={() => {
iframeRef.current.contentWindow.postMessage("10 + 20", "*")
}}>
Trigger iframe eval
</button>
<iframe src="sandbox.html" ref={iframeRef} style={{ display: "none" }} />
</div>
)
}
export default IndexPopup
When a user clicks the trigger iframe eval
, they will see the result of the eval done inside the sandbox page.
See rfc-263 (opens in a new tab) for more details.