10

Is it possible to use eval() to evaluate JavaScript code and be certain that that code will not have access to certain objects?

Example:

(function(window, location){ eval('console.log(window, location)'); })()

The above code doesn't seem to have direct access by reference to the window object because it is undefined in that scope. However, if another object exists globally and it contains a reference to window, it would be accessible.

If I add to window, location any other object or variable that may contain a reference to window, will the evaluated code ever be capable of referencing the window object?

I am trying to create a platform where user apps can be uploaded with js files and access to specific APIs will be given in the form of permissions.

Kosmas Papadatos
  • 1,277
  • 2
  • 14
  • 32
  • 2
    Eval is Evil. Never use it if you are concerned with security. – SharpEdge May 26 '15 at 14:32
  • 4
    You may want to look at some kind of [sandbox library](https://github.com/gf3/sandbox). Writing your own is probably going to lead to failure of the painful sort if there's a lot on the line here. Since you're talking about uploading and executing arbitrary JavaScript, I have no idea how `window` would factor in here. Are you running this in a browser? That seems reckless. – tadman May 26 '15 at 14:33
  • *In theory* I suppose that if you added *every other object* that *might* have a reference to `window` or `location`, it ought to work. Of course, the tricky part then becomes how to ensure there isn't some global object you've missed. I agree with @tadman that you should look at some ready made sandbox solutions first before you try and make your own. – Matt Burland May 26 '15 at 14:36
  • 6
    eval() isn’t evil, just misunderstood – R4nc1d May 26 '15 at 14:39
  • 1
    @R4nc1d That's right, it should be avoided 99% of the time, and this is a case where it may be acceptable, if you know what you are doing. – Ruan Mendes May 26 '15 at 14:41
  • 1
    This is not for a production project, it's solely for academic purposes. I am more interested in learning wether it would be possible to create a secure sandbox environment in, let's say a webpage. – Kosmas Papadatos May 26 '15 at 14:41
  • Keep in mind that with the Developer Tools i'll be always able to execute any arbitrary code on the page. So the sandbox is a little pointless here. – SharpEdge May 26 '15 at 14:43
  • 6
    @KosmasPapadatos A good solution is to run the code in an isolated `iframe` that is not allowed to access the parent page. Then, even if they do modify `window`, it won't really affect your site. You can then communicate with that `iframe` using `postMessage`. That is what sites like http://jsfiddle.net/ do. You'll see that your JavaScript can't really affect the outside of the Result frame – Ruan Mendes May 26 '15 at 14:47
  • @SharpEdge sure but this is to prevent an app from breaching the client. Not the client breaching itself. – Kosmas Papadatos May 26 '15 at 14:48
  • @Juan Mendes that's the solution of JSFiddle! Kosmas Papadatos I see now what you want, try with an iFrame, take a look at JSFiddle. – SharpEdge May 26 '15 at 14:49
  • @SharpEdge Regarding your comment about dev tools, you'll only be able to execute code with your credentials. The problem with running JavaScript is that it can be run under someone else's credentials. – Ruan Mendes May 26 '15 at 14:51
  • @JuanMendes this is a good answer. I was just hoping for something that would securely grant direct access. But then again, if infinite loops are to be taken care of, we would need a web worker for a second thread, so `postMessage` is inevitable. – Kosmas Papadatos May 26 '15 at 14:52
  • @JuanMendes I mean that if the JavaScript to execute contains an infinite loop, it would freeze the whole page. We would need a web worker to do the job so that the main thread is free to declare the app non-responsive and possible terminate it. – Kosmas Papadatos May 26 '15 at 15:00
  • 1
    You might want to have a look at [Making WebWorkers a safe environment](http://stackoverflow.com/q/10653809/1048572). And that's only about WebWorkers, which are already restrained. – Bergi May 26 '15 at 15:12
  • That is a good point, you could execute the user's code in a webworker, which doesn't have access to the window or the DOM – Ruan Mendes May 26 '15 at 15:13
  • In conclusion I think web workers are the best solution to what I'm describing in the question. Since the `this` object always contains a reference to `window`, I guess what I'm asking is impossible. However I'm going to give this some more time in case a JavaScript Guru shows up and comes up with a way to do it :) This is highly unlikely though so if someone posts a complete answer with web workers I would go for it. – Kosmas Papadatos May 26 '15 at 15:21

1 Answers1

3

In JavaScript, any function called globally (i.e. not on an object) will have its this parameter set to the global object (in a browser that is window). So this snippet:

(function(window, lovation) { eval('(function () { console.log(this) })()'); })()

prints out the current window object

Will Smith
  • 1,905
  • 1
  • 14
  • 19