2

One of the guarantees that strict mode provides is that in strict function code, the identifier arguments always refers to that function's Arguments object.

function fn () { 'use strict'; // malicious code arguments // still refers to the function's Arguments object } 

So, no matter what code is injected at // malicious code, the arguments identifier is immutably bound to the function's Arguments object during the entire function invocation.

I was wondering if the same guarantees are provided for the eval identifier, i.e. does the eval identifier with guarantee refer to the built-in global eval function at all times?

I'd like to point out that the above mentioned guarantee is not provided if our strict code is nested within non-strict code. Non-strict code is allowed to create local "eval" bindings, or to mutate the global "eval" binding. (Also, if another non-strict program uses the same global object (as in a web-page containing multiple scripts), the above mentioned guarantee is also not provided.)

So, for the sake of this question, I'd like to define the following scenario:

  • our program is stand-alone, i.e. it doesn't share its global object with any other program,
  • our program consists of a single strict IIFE, like so:

    (function () { 'use strict'; // malicious code eval // does it still refer to the built-in global eval function? }()); 

Given these conditions, is it possible to inject code at \\ malicious code, that will change the value of the eval identifier?

2
  • 2
    I assume you're already aware that the answer is "no" and are just looking for a reference. ;) Commented Sep 27, 2012 at 18:00
  • 1
    @GGG Based on my research, the answer is "no", but I'm learning new things about JavaScript every day, so it wouldn't surprise me if it were possible. Commented Sep 27, 2012 at 18:16

2 Answers 2

2

Theoretically it should not be possible to reassign the eval identifier to something other than the eval property of the global object, or mask it with a local variable, according to annex C:

The identifier eval or arguments may not appear as the LeftHandSideExpression of an Assignment operator (11.13) or of a PostfixExpression (11.3) or as the UnaryExpression operated upon by a Prefix Increment (11.4.4) or a Prefix Decrement (11.4.5) operator.

...

It is a SyntaxError if the Identifier "eval" or the Identifier "arguments" occurs as the Identifier in a PropertySetParameterList of a PropertyAssignment that is contained in strict code or if its FunctionBody is strict code (11.1.5).

...

It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a strict mode FunctionDeclaration or FunctionExpression (13.1)

...and so on.


As discussed below, it's possible to change the global eval function by assigning a new value to that property of the global object. A reference to the global object can be obtained by an indirect call to eval in strict mode:

var glob = (0,eval)('this'); 

You could extend that to something that will work reliably in non-strict mode as well:

var glob = (function(){ return this || (0,eval)('this') }()); 

...and then assign its eval property to something else.

While eval will still be identical to the eval property of the global object, it won't be the built-in eval anymore, which should meet your conditions.

Sign up to request clarification or add additional context in comments.

15 Comments

One thing that I didn't mention in my question is that, had the function from my question access to the global object (and it has not in my scenario), it would be able to change the value of eval by assigning to globalObject.eval. So, for instance, were the function invoked via .call(this) (passing in the global object), instead of (), then this code this.eval = null; would change the value of eval, so, later on, eval // => null. It's things like this, that make me ask for confirmation on SO.
@ŠimeVidas Yeah, I was wondering if you were aware of that... in a browser you could just do window.eval = /* hacks */ from anywhere, that would probably be the approach to take if you wanted to mess with eval. Note the difference in strict mode between direct and indirect eval calls, though.
Ah yes. I forgot that, in browsers, a function doesn't have to worry about retrieving a reference to the global object, since such a reference is omnipresent via window. So, no matter how strict our code is, it is always possible to destroy the built-in eval function by assigning to window.eval. That's certainly a loophole in strict mode. Making the global "eval" binding immutable would have fixed that, but this change wasn't made to prevent legacy programs from breaking (I assume, that's the reason). What a pity.
@ŠimeVidas yes, but even in strict mode you can always get a reference to the global object (through indirect eval, ironically). [eval][0]('this') returns the global object in strict mode (kangax found this).
Are you aware that you've just answered my question? By injecting [eval][0]('this').eval = null; into my example, it is possible to change the value of eval. So, it is possible.
|
0

No, not as far as i can tell, you cannot overwrite the native eval function in strict mode. The code below would give the following error. SyntaxError: Assignment to eval or arguments is not allowed in strict mode

(function () { 'use strict'; eval = function(){ console.log('eval invoked'); } eval(); }()); 

1 Comment

We've established that it can be done. See comment section of GGG's answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.