Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a worker in a sandboxed iframe?

I am building a sandbox for running untrusted code. For this reason I create a sandboxed iframe (which only has the allow-scripts permission set in its sandbox attribute) in order to protect the origin, and then inside that iframe I create a web-worker to ensure a separate thread and prevent freezing the main application in case the untrusted code has an infinite loop for instance.

The problem is, if I try to load the sandbox over https, recent Google Chrome does not allow to create a worker. On other browsers it works, and it also works if I load the sandbox in Chrome via http.

Here is the code:

index.html:

<!DOCTYPE html>
<html>
  <head>
    <title>Sandbox test</title>
    <script type="text/javascript" src="main.js"></script>
  </head>
  <body></body>
</html>

main.js:

// determining absolute path of iframe.html
var scripts = document.getElementsByTagName('script');
var url = scripts[scripts.length-1].src
    .split('/')
    .slice(0, -1)
    .join('/')+'/iframe.html';

window.addEventListener("load", function() {
    var iframe = document.createElement('iframe');
    iframe.src = url;
    iframe.sandbox = 'allow-scripts';
    iframe.style.display = 'none';
    document.body.appendChild(iframe);

    window.addEventListener('message', function(e) {
        if (e.origin=='null' && e.source == iframe.contentWindow) {
            document.write(e.data.text);
        }
    });
}, 0);

iframe.html:

<script src="iframe.js"></script>

iframe.js:

var code = 'self.postMessage({text: "sandbox created"});';
var url = window.URL.createObjectURL(
    new Blob([code], {type: 'text/javascript'})
);

var worker = new Worker(url);

// forwarding messages to parent
worker.addEventListener('message', function(m) {
    parent.postMessage(m.data, '*');
});

Demo:

http://asvd.github.io/sandbox/index.html - http demo (works everywhere)

https://asvd.github.io/sandbox/index.html - https demo (doesn't work in Chrome)

https://github.com/asvd/asvd.github.io/tree/master/sandbox - source (exactly as inlined in this question)

Google Chrome then complains:

Mixed Content: The page at 'https://asvd.github.io/sandbox/iframe.html' was loaded over HTTPS, but requested an insecure Worker script 'blob:null/a9f2af00-47b1-45c1-874e-be4003523794'. This request has been blocked; the content must be served over HTTPS.

I also tried to load the worker code by https from a file instead of a blob, but this is not permitted anywhere, since I cannot access the files of the same origin from an iframe.

I am wondering if there is an opportunity to make such a sandbox work in Chrome, without adding allow-same-origin permission to the iframe.

like image 343
asvd Avatar asked May 31 '15 14:05

asvd


People also ask

What is sandboxed iframe?

The sandbox attribute enables an extra set of restrictions for the content in the iframe. When the sandbox attribute is present, and it will: treat the content as being from a unique origin. block form submission. block script execution.

Why would you use the sandbox attribute with an iframe?

Applying the sandbox attribute to iframes you include allows you to grant certain privileges to the content they display, only those privileges which are necessary for the content to function correctly.

Is iframe sandbox secure?

Now, these are things that have a great security risk, so to make things more secure for the users, W3C added the 'Sandbox' attribute in the HTML specifications. This attribute limits the action from an iframe within a web page and makes it quite secure and protected.


1 Answers

As you have discovered, Chrome won't let you access non-https content (such as a data blob) from a https page, and also treats blob URLs as not being https. And without allow-same-origin, it then can't load any worker script files from any domain.

My only suggestion is to have the iframe served from a separate https-served domain (/subdomain), and then have both allow-scripts and allow-same-origin. Due to being on a separate domain, the code in the iframe still won't be able to access the DOM/data of the parent page.

like image 69
Michal Charemza Avatar answered Oct 15 '22 22:10

Michal Charemza