I want to create an HTML+JS environment where user can enter and run arbitrary JavaScript code which will be executed in context of given jail object. I've set up a playground to illustrate what I have so far.
This one does a somewhat decent job:
- Basic evaluation works:
- Input:
2 + 2
- Output:
4
- Input:
this
returns jail object- Input:
this
- Output:
[object Object]
- Input:
this.hello()
runs expected method- Input:
this.hello()
- Output:
hello world!
- Input:
- User can set up their own functions and execute them later:
- Input:
this.foo = function() { return 42; }
- Output:
function () { return 42; }
- Input:
this.foo()
- Ouput:
42
- Input:
- Trying to access some object that I want to stay "hidden" from jail context fails:
- Input:
hidden
- Output:
ReferenceError: hidden is not defined
- Input:
However, it completely fails to hide globally accessible properties, such as window
or document
for user:
- Input:
window
- Current output:
[object Window]
- Desired output:
ReferenceError: window is not defined
The best solution I've came up so far is to just fill up all the global variable I can think of with undefined
or null
right in the Jail object declaration, as illustrated in updated version. This way they seem to be lost forever inside the scope of jail and user won't be able to access them. My questions:
- Am I right? Is this safe enough?
- Is there any better way, i.e. to really undefine global stuff in certain scope instead of rewriting them with some placeholder values?