sandbox > extension page can not access chrome.runtime.sendMessage anymore?

527 views
Skip to first unread message

André Bonin

unread,
May 4, 2022, 10:29:59 AM5/4/22
to Chromium Extensions
Hi there,

my extension is manifestV3.
In one of my extensions pages I'm trying to insert an iframe. The source code of that iframe is base64 encoded html (data uri). This iframe has all code inline, even the js. That code is trusted.

Now I try to use CSP settings in order to allow the inline-js execution within this iframe.
Those CSP settings are set everywhere (iframe source code, extension page source code, sandbox-settings in manifest).

Manifest:
    "content_security_policy": {
"extension_pages": "script-src 'self'; object-src 'self'",
"sandbox": "sandbox allow-scripts; script-src * 'self' 'unsafe-eval' 'unsafe-inline' blob: filesystem: data:; object-src blob: filesystem:;img-src * data:;style-src 'self' 'unsafe-inline'"
},
"sandbox": {
"pages": [
"some-page.html"
]
},

iframe CSP:
<meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'; img-src * data: ">

some-page.html CSP:
<meta http-equiv="Content-Security-Policy" content="default-src *;frame-src * data: ; style-src 'self' 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'; img-src * data: ;object-src 'self' blob: filesystem:">

some-page.html contains a reference to some local js, that also ships with the extension:
<script src="./some-script.js"></script>

When I use the sandbox-setting, the code in some-script.js can not even send a message using  chrome.runtime.sendMessage:
csp-issue.png
if I remove the sandbox-settings in manifest.json, I receive CSP errors (inline js)

How can I achieve this?

wOxxOm

unread,
May 5, 2022, 10:51:19 AM5/5/22
to Chromium Extensions, André
Use parent.postMessage instead?

stev...@hotmail.com

unread,
Dec 11, 2023, 7:56:01 PM12/11/23
to Chromium Extensions, wOxxOm, André
Hi wOxxOm,

Is it possible to communicate between the sandbox webpage and the background service worker without using the sandbox webpage inside an iframe?

Cheers,
Steven.

wOxxOm

unread,
Dec 11, 2023, 8:52:16 PM12/11/23
to Chromium Extensions, stev...@hotmail.com, wOxxOm, André
Do you mean when opened in a tab?
In that case you can do it via the offscreen document and MessageChannel:

// service worker
openSandbox().then(sbPort => {
sbPort.onmessage = console.log;
sbPort.postMessage('foo');
});

async function openSandbox(url = 'sandbox.html') {
  try {
    await chrome.offscreen.createDocument({
      url: 'offscreen.html',
      justification: 'foo',
      reasons: ['BLOBS'],
    });
  } catch(e) {
    if (!e.message.includes('single offscreen document')) throw e;
  }
  const mc = new MessageChannel();
  const doc = (await clients.matchAll({includeUncontrolled: true}))
    .find(c => c.url.endsWith('/offscreen.html'));
  doc.postMessage({cmd: 'sb', url}, [mc.port1]);
  return mc.port2;
}

// offscreen.js
navigator.serviceWorker.onmessage = evsw => {
  if (evsw.data.cmd === 'sbPort') {
    const sb = window.open(evsw.data.url);
    addEventListener('message', function fn(evsb) {
      if (evsb.data === 'sb' && evsb.source === sb) {
        removeEventListener('message', fn);
        sb.postMessage('swPort', '*', evsw.ports);
        window.close();
      }
    });
  }
}

// sandbox.js
let /** @type {MessagePort} */ swPort;
opener.postMessage('sb', '*');
window.onmessage = e => {
  if (e.data === 'swPort') {
    swPort = e.ports[0];
    swPort.postMessage('hello');
    swPort.onmessage = console.log;
  }
};

stev...@hotmail.com

unread,
Dec 12, 2023, 3:58:32 PM12/12/23
to Chromium Extensions, wOxxOm, stev...@hotmail.com, André
Thank you for the prompt response!

Yes, when opened in a tab. Thank you for the code example, I was also hoping there was a way without using an offscreen doc also but I assume not.

Thanks again for the help!

stev...@hotmail.com

unread,
Dec 12, 2023, 4:23:38 PM12/12/23
to Chromium Extensions, stev...@hotmail.com, wOxxOm, André
I believe using this method will not work for me. If the user refreshes the tab or loads it directly, the connect will be lost.

My user case is: I have a screenshot/recording extension with an editor/options page which needs a sandbox environment to be able to load a script from a payment provider.

The only interaction with chrome apis I require is loading the extension settings from chrome.storage.

stev...@hotmail.com

unread,
Dec 12, 2023, 4:27:29 PM12/12/23
to Chromium Extensions, stev...@hotmail.com, wOxxOm, André
On second thought I also need access to chrome.i8ln and chrome.identity.

I may have to extract the payment logic to outside of the chrome extension 😩. Any workarounds/thoughts are greatly appreciated.

wOxxOm

unread,
Dec 12, 2023, 4:27:47 PM12/12/23
to Chromium Extensions, stev...@hotmail.com, wOxxOm, André
Why do you sandbox the entire page of the extension? Can you simply a) open the site in a tab with your content script or b) show the site in an iframe inside an extension page?
Reply all
Reply to author
Forward
0 new messages