I've done some research on sandboxing in JavaScript and Node.js. Below are some of my findings.
Seven Degrees of Sandboxing: 1. restrict direct read-access to not explicitly white-listed properties of the global object 2. restrict direct write-access to the global object so that it cannot be extended 2. restrict direct write-access to the global object so that its properties cannot be mutated 4. strict mode: lexical scoping (yay!), no global object 5. strict mode with frozen context 6. strict mode with frozen context, running as a separate process 7. strict mode with frozen context, running as a separate process in a chroot environment or jail Note that without lexical scoping (i.e., in unrestricted mode) proper sandboxing is conceptionally hard, and in practice maybe even impossible. For instance, a function can access properties that are outside of its scope via `arguments.callee`. In an environment like Node.js, there are probably several other ways to do so. In strict mode, sandboxing is probably pretty straight-forward. For instance, a function `runInSandbox` that executes some other function in a sandbox with a frozen context and no global object could be as follows: function runInSandbox(src, ctx) { var vm = require('vm'), sandbox = Object.freeze(vm.createContext(ctx || {})), script = vm.createScript('(function() {"use strict"; return (' + src + ')()}())'); return script.runInContext(sandbox); } With such type of sandboxing function, we can put our own secure version of `require` into the sandbox's context. When called, that secure require function would check against a black or white list whether that module is secure and can be required, and then according to that either require the module or throw an exception. Would it be an issue for you to constrain the execution of JavaScript to be in strict mode only by default? On Thu, 2013-01-31 at 16:54 +0000, Jason Smith wrote: > On Thu, Jan 31, 2013 at 4:34 PM, Benoit Chesneau <bchesn...@gmail.com>wrote: > > > > > A javascript engine doesn't expose any IO par default. The **framework** > > nodejs is, this is all the point. I'm quite interested by the existing > > solutions to sandbox nodejs, do you know some projects that does it? > > > > Correct. I am attempting to build something which satisfies your > description: no i/o; i/o is not even possible. > > *How* is it implemented? Well, it doesn't matter whether we use Node.js or > couchjs/SM or couchjs/v8. What matters is we feel confident about security. > And of course, I agree, if we cannot achieve good security, then that is a > show stopper. > > Here is my current plan for sandboxing CouchJS. (Thanks to Isaac for his > tips.) > > When it is time to evaluate some code: > > 1. Set up an object with safe variable bindings: safe_context > 2. fork() > 3. Child process runs vm.runInNewContext(safe_context) > 4. Child process communicates to the parent over stdio, through the > approved safe_context functions > > The subprocess can also give extra sandboxing, such as chroot() if > available. > > Yes, this causes two processes per instantiation; however I think the > parent might only be short-lived, setting up the security, then exiting. > The grandchild can talk to Erlang over stdio. > > That is my plan. No idea how well it will work. >