Javascript use of Eval(): what are the pros and cons?

Asked

Viewed 9,448 times

25

Recently I met this function and I was surprised by its power, it was of great use to me, but after using it I heard comments that it was not safe.

I would like to know in situation this use can cause security problems and if there is alternative to Eval() when you want to generate javascript code dynamically, but in a more secure way.

Example of use by my application:

var valPeriodos = "";
var next = ".next()";

for (i = 1; i <= numPeriodos; i++) {
    eval('var tdVal' + i + '=$(this).parent().parent().find(".vp1").parent()' + valPeriodos + ';');
    valPeriodos += next;
    eval('val_' + i + ' = tdVal' + i + '.find(".valInputOn").val()');
}

In this code I take values from a dynamic table that has columns according to the number of periods and save them in variables.

  • Please include some examples where you think Eval was of great use. So you can point out the pros and cons more concretely. The problem with Eval is that in most cases generating code dynamically is a bad idea because it is much simpler to think about static code and you have to worry less about escaping inputs that comes from the user.

  • Here’s an example. If I were to do it in a traditional way, I would spend dozens of lines of code. Besides, if you needed some maintenance it would be much more complicated to change line by line.

  • It is possible (and advisable) to avoid eval in your example, even keeping the loop. But this requires changes to other parts of the code (array or object instead of variables val_N).

  • What is in this variable valperiodos? I’m not understanding your example.

  • I added to the code @missingno

3 answers

15


I also have to answer because val() not as bad as many people think, it depends on how and where you use it. Driving a car is dangerous if you don’t know how to do it.

For those who do not master javascript Eval can scare. And then it is easier to generalize and say that you should never use. Now is not the case.

Eval is one of the most powerful tools in javascript. It is a parser in itself. The biggest problem of Eval arises when connected to the communication with the server. But if you use Eval in internal code functions, without external input Eval can be very useful and secure.

It is worth mentioning (and take into account) that any user can come to a website, open the console and run malicious code with Eval.

In the case of having Val on lines of code that link to a database for example, it is important to make shielding possible attacks. In these cases avoid the Eval.

The first part of my response is positive to Val, to say that there are cases where it is useful (as here for example).

But he has weight cons:

  1. Misuse of Eval can lead to code injection attacks

  2. Harder to debug (since within Eval errors have no line indication)

  3. slower than similar code without

  4. hinders and limits the minification of the code

Finally it’s worth mentioning that Eval is used in hidden javascript. More about this in this question.

  • 3

    Very good, very good. Someone with an impartial view on the eval +1

14

The eval, in certain situations makes your code to be...

  1. ... harder to understand: javascript is being compiled on time, which, in addition to slowing down, makes it vary according to the variable that is inserted in the function;
  2. ... more insecure: you’ve heard of SQL injection? eval is an open door to it, only in another language;
    Use 'use strict' prevents an attacker from having access to private variables, but it does not protect global variables, so if you have to eval validate the code before executing it.
  3. ... harder to work: tools like the Closure Compiler and the Uglify cannot work with the eval in certain situations. The function prevents these tools from finding the variables defined and organising them.

But there are situations where I use eval is accepted - according to the Google style guide:

  • If you are programming a REPL, example:
!function r(i){i=prompt('Insira um comando:');if(i)alert(eval(i)),setTimeout(r)}()
  • If you are programming a code loader: the Requirejs, for example, uses eval.

Editing: an example of code was added to the question, that answer that same code rewritten without using eval.

  • 2

    Another important point is that the simple presence of eval inhibits huge optimization opportunities on the part of the implementation. If performance is important, it is another reason to avoid.

  • I understood most of your answer, but I’m still too beginner to understand this little code you wrote! What does it do?

  • 1

    It is a REPL. Renaming variables and organizing: https://gist.github.com/qgustavor/8810385

  • @Joaopaulo: That code does something like while(1){ var cmd = prompt('Insira um comando:'); if(cmd){ alert(eval(i)); } }

  • @missingno It’s a little different: it would be more do{var cmd = prompt('Insira um comando:');if(cmd){ alert(eval(cmd));}}while(cmd) - (is a do-while)

  • Months later and I see that it could compress much more this code.

Show 1 more comment

2

In the example you gave, the alternative to Eval would be to use a vector instead of a bunch of separate variables:

var vals = [];
var tdVals = [];
var tdAtual = $(this).parent().parent().find(".vp1").parent()
//Vetores em Javascript são normalmente indexados começando do zero então mexi no seu loop.
for (i = 0; i < numPeriodos; i++) { 
    tdVals[i] = tdAtual;
    vals[i] = tdAtual.find(".valInputOption").val();
    tdAtual = tdAtual.next();
}

Some of the advantages that this code has compared to the version using Eval:

  • It’ll be easier to debug. In case of error, the debugger points the line of code better, you can mark breakpoints, inspect the contents of variables, etc.
  • It will be easier to use tools that scan your code without running it, like Jshint (I strongly recommend using something like this if you’re not using it!). Usually these tools get totally lost if they find an Eval.
  • Vectors are a first class object in JS, unlike their dynamic variables. You can pass them from one side to the other, you can look at the tdVals.length rather than having to maintain the value of numPeriodos separately, etc..
  • The scope of your variables becomes clearer. You can see right away what are the names of the two vectors that I’m creating and it’s easier to know if the variables are global and local.
  • The algorithm has become simpler and more efficient. Now it gives a next only for each td instead of 1 for the first, 2 for the second, etc.
  • I think it’s gotten easier to understand. A code using Eval can potentially do anything, which means it has to be read more carefully.
  • Very good answer. Really gave to realize the advantages of not using Eval() and an alternative even more efficient and with little code. I’m going to start using vectors. I’m still very new to JS and I hadn’t even thought about that possibility.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.