Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to safely run user-supplied Javascript code inside the browser?

Tags:

Imagine a scenario where I want to continuously invoke user-supplied Javascript code, like in the following example, where getUserResult is a function that some user (not myself) has written:

for (var i = 0; i < N; ++i) {     var x = getUserResult(currentState);     updateState(currentState, x); } 

How can I execute that kind of code in a browser and/or Node.js, without any security risks?

More generally, how can I execute a Javascript function that is not allowed to modify or even read the current webpage or any other global state? Is there something like an in-browser "JS virtual machine"?

How does JSFiddle ensure that you cannot run any malicious code (at the very least it could phish your login name, run a bot for the lifetime of the page, if not do much worse things)? Or doesn't it ensure that at all?

like image 304
Domi Avatar asked Mar 19 '14 12:03

Domi


People also ask

Is it safe to allow JavaScript in web browser?

JavaScript is fairly safe to run in most browsers. But that's not the same thing as “perfectly safe.” Because it's a script from a website that's executed on your computer, it can contain malware and exploits. Most JavaScript that websites use is third-party library that's open-source.

Can JavaScript only be executed on the browser in the client?

Today, JavaScript can execute not only in the browser, but also on the server, or actually on any device that has a special program called the JavaScript engine. The browser has an embedded engine sometimes called a “JavaScript virtual machine”.

How does browser handle JavaScript?

The script sections of a web page are handled by the browser's JavaScript interpreter, which may be an intrinsic part of the browser but usually is a distinct module, sometimes even a completely distinct project (Chrome uses V8; IE uses JScript; Firefox uses SpiderMonkey; etc.).


1 Answers

After much consideration and with the help of other posters in this thread (thank you so much for your help!), I found a first bunch of answers to my questions. I am re-writing my answer here though, because it summarizes the concepts and also gives you some actual code to experiment with.

Generally, there are two solutions to this problem: We can either use iframe or Worker to run code in an isolated environment, thus making it impossible to read or write the current page's information (which is my first major security concern).

Caja + Closure

There are more complete sandbox solutions such as Google Caja, which (by default) also runs its code in an iframe. Caja does not only sandbox JS, but also HTML and CSS. However, it does not seem very actively maintained anymore.

Update: Caja has been deprecated since the original posting. It has been replaced with the Closure Toolkit, specifically Closure Library and Closure Templates.

WebWorker + Blacklisting

As proposed by Juan Garcia, I am going with the web worker API, but that is not the complete story. Even though, the worker cannot directly access anything from the hosting page, there are still quite a few security risks. This site lists all built-ins available in a Worker's context.

This JSFiddle demonstrates a way to run a string of code outside the window's context without having to go through the server, which is still unsafe, as pointed out in the comments.

I have extended on that and employed a black-list based approach to disable all outside communication by taking away all of the following:

  • Worker
  • WebSocket
  • XMLHttpRequest
  • importScripts

Webworker + Whitelisting

The actually safest approach however, is a white-list approach, (mentioned here), as it will stay safe into the future (given that the semantics of any whitelisted globals will never change in such a way that they allow more access in any future release; which is a somewhat reasonable assumption).

I ended up implementing the whitelist approach in my in-browser WumpusGame that allows you to write your own AI script while playing the game, a few years back. Source code here. You can see that the Whitelist is maintained in GuestScriptContext while the workers are managed by the HostScriptContext.

The GameScriptContext shows how you can use it.

It has several features, including guest<->host communication, guest can execute non-privileged actions (and if it has a security token even privileged actions) on the host, and a lot more.

NOTE: It does not play well with some extensions, as they will prevent overriding globals (when I try to run it, it complains about TEMPORARY being one of them). The fix would be to either whitelist those, or figure out how to make it play nice with modern browser security features, or just security-focused extensions, such as AdBlock etc.

The game is theoretically playable here, but because of reasons above it does not seem to work in Chrome (and I haven't tried other browsers yet).

Some more references:

  • The W3Schools web worker tutorial.
  • This thread and this html5rocks tutorial on how to run a Worker without separate files.
like image 101
Domi Avatar answered Sep 29 '22 14:09

Domi