Search code examples
javascripthtmliframefetchsandbox

Loading file into sandboxed iframe without using a fetch request


I'm trying to load a file in an iframe without performing a fetch request. I want to run the code inside a sandboxed iframe WITHOUT the "allow-same-origin" permission in order to protect the end user from malicious code. And since the iframe creates unique origins for each individual fetch call I can't call the file from the server without the "allow-same-origin" permission.

If you create a sandboxed iframe and add both the "allow-same-origin" and the "allow-scripts" permissions, the sandbox attribute becomes far less useful as a security feature. Firefox provides a warning for this vulnerability: "An iframe which has both allow-scripts and allow-same-origin for its sandbox attribute can remove its sandboxing." So I need a way to exclude the "allow-same-origin" permission.


Solution

  • To do this you need control over the embedded iframe and the parent window. The iframe can have the sandbox attribute and will only need the "allow-scripts" permission to allow it to run Javascript code. You will need to perform the fetch call from the parent window, get the response and pass it down to the iframe window in a message using the window.postMessage() function. My use case required the file to be processed as a Blob therefore I processed the fetchs response accordingly.

    Code in the parent window:

    fetch(file_url).then(function(response){
      setFrame("./app/NimbleGameEditor/index.html");
      response.blob().then(function(response_blob){
          document.getElementById("DynamicIFrame").onload = function() {
            document.getElementById("DynamicIFrame").contentWindow.postMessage(response_blob, "*");
          }
      });
    });
    

    Code in the iframe window:

    window.addEventListener("message", (event) => {
      if (event.origin == parentWindowURL){
            console.log("Processing data");
            doSomethingWithBlob(event.data);
        }
        else{
            return;
        }
    }, false);
    

    This way you can avoid using the "allow-same-origin" permission, and still download the file without performing a fetch call inside the iframe.