7

I've done my research and there are a few robust ways to sandbox user JS, namely:

  • Use a JS VM that runs the JS using a sandboxed form of js, like VM.js
  • Use a transpiler like Google Caja, which adds additional checks to preserve certain invariants and disallows specific codepaths
  • Use a cross-domain (and/or sandboxed) iframe, potentially with a WebWorker as well, e.g. Jailed

Unfortunately, none of these work well out of the box for my application. I'm trying to build a jsperf.com alternative (i.e. web-based JS benchmarking system), so the first two are out, since they would affect the performance of the user-supplied code, which completely invalidates any benchmarking results.

Jailed is closer, but also not a great alternative because A) its whitelist-only approach is so restrictive that my site would not be able to test the performance of a lot of features of the web (DOM operations, IndexedDb, WebWorkers, LocalStorage, etc.) without a lot of whitelisting that I'm not even sure would work and B) I'm not sure how well maintained (and thus secure) it is given how little activity there is on its GitHub repo.

What is the most permissive system (in terms of closeness to running unsandboxed) that I can safely use to execute user-supplied JS for benchmarking? Is a sandboxed iframe sufficient so the benchmarks can at least access some DOM and other Web APIs? Is the WebWorker really necessary? What do jsfiddle and the like do?

0x24a537r9
  • 171
  • 1
  • 1
    The cross-domain `sandbox`ed `iframe` should be your best bet to do this in-browser. – Alexander O'Mara Sep 01 '16 at 06:35
  • if you're testing performance, you don't want to rewrite or tramp on the code, or you'll be testing something other than the code. An iframe from a dataURL has a different domain, so the SOP should protect the `top` and force the use of `postMessage()`. I don't see how an iframe sandbox would really help you accomplish what you describe, since you probably want wide compat... – dandavis Sep 01 '16 at 10:15
  • Hmm, not having studied it, i thought jsfiddle executed user provided code in a server environment, not on the client. – Jonah Benton Sep 02 '16 at 02:52
  • @AlexanderO'Mara do you have some docs/explanation on why that is sufficient? – 0x24a537r9 Sep 02 '16 at 21:39
  • @dandavis The sandbox attribute provides a lot of things above and beyond what the CORS policy enforces: http://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/. I actually don't care that much compatibility wider than what already supports sandboxing: http://caniuse.com/#search=sandbox. Oh also a data URI is not sufficient, since it still allows access to the top page's localstorage, cookies, indexeddb, etc. – 0x24a537r9 Sep 02 '16 at 21:41
  • @JonahB, no jsfiddle is all client-side in a cross-domain iframe. I'm just not sure if they do anything else that I'll need to. – 0x24a537r9 Sep 02 '16 at 21:42

1 Answers1

1

The software engineering definition of a sandbox is an execution environment with specific security constraints maintained. This means that the user JavaScript should not be able to either leverage or impact the JavaScript of the containing web page.

An iframe implementation will neither

  • Guarantee that the sandbox code run-time conditions will be the same as if it ran in an independent document nor
  • Ensure the parent document will not be impacted and possibly crashed by the sandbox code.

If you have sufficient network and web server control, you can establish fairly secure independence and an authentic execution environment by allowing an authenticated user via HTTPS to provide sand-boxed JavaScript to a completely independent secondary site or sites. Use of sub-domains can reduce the cost of this approach. You may have to use the target='_blank' hack that some consider a violation of the www model.

To be careful not to create security holes with this arrangement, there are a few recommendations.

  • Use a server-side include that precisely acquires the sandbox code.
  • Carefully tighten all web server directory access.
  • Validate the syntax of the JavaScript.
Douglas Daseeco
  • 614
  • 3
  • 17