I have an extension where I need to evaluate user-written JavaScript code. Rather than just calling eval()
on it, I want to execute it in some kind of sandbox.
Mostly because I’m using symlinked modules in my sources, which Firefox refuses lo load directly, I started coding with chrome first.
In chrome I can create an attach an <iframe sandbox="allow-scripts" src="blob:chrome-extension://..."></iframe>
to the head
of my background script, .postMessage()
an MessageChannel
port to it and start sending requests to have scripts evaluated in that sandbox. From within that sandbox the evaluated code has absolutely no chance of doing anything more destructive than messing up the inside of the sandbox (I have considered freezing every last element in the global scope to effectively prevent that …).
I’m pretty sure this is a perfect solution - which only works in Chrome so far.
The problem is that to set up the MessageChannel connection and to do the evaling, I obvoisly need to run some initial code in the sandboxed iframe.
The CSP in WebExtensions won’t let me do that. In chrome I can just concat some modules and functions into the markup in the Blob
and it works. Firefox doesn’t like the inline script.
Linking scripts from the extension doesn’t work - and shouldn’t, it’s supposed to be a sandbox after all.
And sadly the 'unsafe-inline'
directive is not allowed in the CSP, neither are 'nonce-*'
es.
Moving the code into a blob:
-url doesn’t help either.
The only thing I haven’t tried yet is adding a 'sha256-...'
exception, but that would require some pretty annoying changes in my quire dynamic code.
For now I can only add 'unsafe-eval'
to the CSP and eval directly in the elevated background page.
Is there any (other) way to run code in an isolated environment?
Here is the code that works in Chrome: