5

So SharedArrayBuffer was recently limited to Cross-origin isolated pages as a security fix.

We have a tool that depends on SharedArrayBuffer, I reworked it to work again by moving it to a barebones page stripped of all other site UI and what not and sending the following headers:

Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin

Trying to load it in an iframe of the full-fledged site gives me the console errors SharedArrayBuffer will require cross-origin isolation as of M92 followed by ReferenceError: SharedArrayBuffer is not defined - same as I was getting before I cross origin isolated the tool on the minimal page itself.

The page I'm trying to include the iframe in is not cross-origin isolated. It would be very difficult if not impossible to do so. I don't need to talk to the iframe from the parent page at all, it's just a convenience/stylistic thing. The current solution on production right now is just to link users to the minimal cross origin tool page in a new window, but that's pretty awkward.

What I'm hoping is that there is some combination of iframe sandbox attributes or something that would make this work? I fought with this for a couple hours.

This may not be doable for all I know.

donatJ
  • 3,105
  • 3
  • 32
  • 51

2 Answers2

1

Try adding allow-scripts and allow-same-origin tokens in the iframe's sandbox attribute:

<iframe src="…" sandbox="allow-scripts allow-same-origin"></iframe>
                         ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^

Here are some relevant resources on the topic:


Try the above first, and if it didn't help with the SharedArrayBuffer problem you have, then things are a bit more complex.

Proper cross-origin requires explicit headers from the subresources (the <iframe> has to send headers), which is a big problem when the subresources are third-party and out of control. To mitigate this problem, there is a proposal Cross-Origin-Embedder-Policy: credentialles.

However, there's a catch: it doesn't change how <iframe> works (bummer, this is exactly what's needed!). There's a discussion about anonymous iframes, that would solve this issue, but it is not resolved yet, so I'm wouldn't hold my breath here.

So, the only option that's left is to delay this change in Chrome behavior (which can be done before Chrome 103):

  1. Request a token for your origin.
  2. Add the token to your pages. There are two ways to do that:
    • Add a <meta> tag to the head of each page. For example, this may look something like: <meta http-equiv="origin-trial" content="TOKEN_GOES_HERE">
    • If you can configure your server, you can also add the token using an Origin-Trial HTTP header. The resulting response header should look something like: Origin-Trial: TOKEN_GOES_HERE
Parzh from Ukraine
  • 7,999
  • 3
  • 34
  • 65
0

I'm not sure if this option is a solution in your case, but maybe it can help you find a complete solution. This blogpost describes enabling SharedArrayBuffer via header modification in ServiceWorker. It works in the following order:

  1. When the page is loaded for the first time, a Service worker is registered
  2. The page is reloaded
  3. SharedArrayBuffer becomes available because ServiceWorker controls all CORS headers for all requests

Service Worker modifies all requests by adding CORS/COEP headers (The example is taken from the mentioned blogpost):

self.addEventListener("install", function() {
  self.skipWaiting();
});

self.addEventListener("activate", (event) => {
  event.waitUntil(self.clients.claim());
});

self.addEventListener("fetch", function(event) {
  if (event.request.cache === "only-if-cached" && event.request.mode !== "same-origin") {
    return;
  }

  event.respondWith(
    fetch(event.request)
    .then(function(response) {
      // It seems like we only need to set the headers for index.html
      // If you want to be on the safe side, comment this out
      // if (!response.url.includes("index.html")) return response;

      const newHeaders = new Headers(response.headers);
      newHeaders.set("Cross-Origin-Embedder-Policy", "require-corp");
      newHeaders.set("Cross-Origin-Opener-Policy", "same-origin");

      const moddedResponse = new Response(response.body, {
        status: response.status,
        statusText: response.statusText,
        headers: newHeaders,
      });

      return moddedResponse;
    })
    .catch(function(e) {
      console.error(e);
    })
  );
});
Oleg Barabanov
  • 2,468
  • 2
  • 8
  • 17
  • This doesn't solve my problem, this just alleviates the need to set the headers which isn't a problem I have. I am perfectly able to set the headers server side. I already have the tool itself working on a page with the headers set and nothing else. The problem is the headers break everything on the normal site, namely loading JS from a CDN. Reworking the entire site and maintaining the changes for this tool an option. This is why I wanted to load the minimal working tool in an iframe - I'm getting the sense that it isn't possible but I'm not sure why such a restriction would exist. – donatJ Dec 13 '21 at 08:22
  • Then, as far as I know, there is currently no way to use a Shared Array Buffer inside an iframe. This has already been discussed here https://stackoverflow.com/questions/69322834/is-it-possible-to-embed-a-cross-origin-isolated-iframe-inside-a-normal-page/69363428 – Oleg Barabanov Dec 13 '21 at 08:51