I avoid using eval()
or Functions created from a string. But when I need to run some subset of Javascript that can be entered by a user I'm tempted to use it just because it will save me much work writing a lexer/parser and interpreter.
Say I'd like to run this code:
a.toLowerCase() === 'xyz' || b == 1 || /pqr/.test(c)
the native approach would be to pass it into eval()
like this:
with({a: ..., b: ..., c: ...}) {
ret = eval(code);
}
I cannot be sure that code
always contains uncritical code like the above. This opens the possibilities to run malicious code.
I thought of passing an object re-defining critical Browser objects to with
besides the actual data like:
var obj = {
// list incomplete ;)
console: true, XMLHttpRequest: true, document: true, window: true, addEventListener: true, removeEventListener: true, parent: true, top: true, history: true, ...,
// actual data
a: ..., b: ..., c: ...
};
with (obj) {
...
}
When running code within with
access to the objects/methods is not possibe.
I know that it's still possible to indirectly access those methods if they are indirectly accessed though another object/function that is not re-defined. Let's assume I re-define these too.
Is it secure to sandbox code with a suffient list of objects and functions as content object?
What would be remaining the attack vectors in this case?
The code should run within Firefox, Chrome, IE (10+), Opera, Safari.
No, this is not secure.
No matter what you do with your code's execution environment using with
, it is still possible to retrieve the "real" global object using the following trick:
var window = (function(){ return this }).call(undefined);
This works because Function.call
will use the global object as the value of this
if it is explicitly passed as undefined
or null
.