Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript: possible for parent to kill child iframe if it is stuck in an infinite loop?

I have a page that has an iframe with external content. I don't want infinite loops in the external content to crash my whole page. Is there any way to get around this.

I tried to set something up where the parent postMessages the child iframe every so often and if the child Iframe doesn't respond for too long a time the parent changes the iframes src, but this doesn't seem to work. The parent's setTimeout functions no longer execute once the iframe starts looping. See my code here (note that it will crash your tab if you execute it, open the console before execution to view the logging):

<html>
<head>
</head>
<body>
<script type="text/javascript">
var scr = 'script';
var html = '<html><head><script>\n' +
'  window.addEventListener("message", answer, false);' +
'  function answer() { console.log("answered"); parent.postMessage(\'hi\', \'*\');}' +
'  setTimeout("while(1){console.log(\'in loop\')};", 3000)' +
"</" + scr + "></head><body>IFRAME</body</html>";

var lastAnswer = (new Date()).getTime();
var iframe = document.createElement('iframe');
queryChild();

window.addEventListener("message", receive, false);
function receive() {
  lastAnswer = (new Date()).getTime();
  console.log('got answer');
}

function queryChild() {
  console.log('querying');
  if((new Date()).getTime() - lastAnswer > 5000) {
    console.log('killing');
    iframe.src = '';
  } else if(iframe.contentWindow){
    iframe.contentWindow.postMessage('hi', '*');
  }
  setTimeout(queryChild, 2000);
};

document.body.appendChild(iframe);
iframe.contentWindow.document.open();
iframe.contentWindow.document.write(html);
iframe.contentWindow.document.close();


</script>
</body>
</html>

Any suggestions on how to solve this problem?

like image 561
asutherland Avatar asked Oct 08 '12 21:10

asutherland


1 Answers

My experience with this kind of problem is that unless you can access the external code before feeding it to the iframe (either as an URL or via the srcdoc attribute), the loop will completely interrupt any JavaScript execution.

Whatever kind of timeout functionality you implement, it will not be called due to the iframe code execution consuming 100% resources until the browser reports a crash.

Your options are:

  • Sanitize the code automatically before adding it to the iframe, which proves impractical since there are infinite ways to loop infinitely, and you will not be able to catch them all. You would have to write a scanner script that could detect infinite loops while not crashing in the course of scanning the code.
  • Use a sandboxing solution like Google Caja to sanitize the code. However, this will change the code structurally if not configured heavily.
  • In case of an application that has capabilites of creating virtual environments and monitoring them, you could execute the iframe code (let's say on a virtual machine of sorts), check if the process locks up and use that outcome to determine if you can safely set the iframe.src property to your code's URL. This might be the only solution that can guarantee some sort of guarantee that this code will not lock up immediately (however, there are many ways to have race conditions at some later point of execution, so there will not be a sure way to say it will never lock up the browser).

Summary: Unless you can find a way to test the code extensively before showing it in the iframe, you can not guarantee that the iframe code will not lock up the browser tab.

like image 74
arvidkahl Avatar answered Oct 04 '22 10:10

arvidkahl