Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Eval is a notoriously controversial language feature. Douglas Crockford flat out rejects it. I'm wondering what specific risks Eval brings about. According to this question, Improper use of eval opens up your code for injection attacks.

What are some improper uses of the Eval command, and what security holes do they open up?

share|improve this question
add comment

6 Answers

Back when I was implementing the JScript engine I advocated having EVAL IS EVIL shirts printed up but sadly we never got around to it.

My biggest problem with eval is not the obvious malicious code injection attack, though that is certainly of enormous concern. My biggest problem with it is that people tend to use it as a Really Big Hammer to solve really small problems. Most of the real-world usages I saw of "eval" in the wild when I was on the JScript team could have been trivially solved by using a lookup table; and since every object in JScript already is a lookup table it's not like that was an onerous burden. Eval starts the compiler again and completely destroys the ability of the compiler to optimize your code.

For some more thoughts in this vein see my articles from 2003 on the subject:

General evilness:

http://blogs.msdn.com/b/ericlippert/archive/2003/11/01/53329.aspx

Injection attack evilness:

http://blogs.msdn.com/b/ericlippert/archive/2003/11/04/53335.aspx

share|improve this answer
    
What are your thoughts on evaling large chunks of code the way that applications like JSPacker like to? JSPacker + gzip usually results in smaller file sizes than either solution on its own, but as you rightly point out it is essentially firing up a compiler twice on the same piece of code, plus some overhead to do string replacements. –  Matthew Scharley Mar 22 '11 at 9:06
2  
@Matthew: There is often a tradeoff between space and time, and taking advantage of that tradeoff can sometimes be a big win. If the purpose of the technique is to improve performance then my opinion is that if careful measurement shows that it is a significant win in realistic scenarios without introducing security holes, great, do that. But I don't know enough about the specific technique to criticize its details. –  Eric Lippert Mar 22 '11 at 14:02
    
I wish one of the answers I had seen either here or on SO itself would have stated what your second link states: that eval() is not a security risk on client (browser) code. –  sq33G Dec 25 '11 at 11:50
add comment

Most of the security holes are the same sort of holes as with SQL injection, namely concatenating user input into JavaScript code. The difference being that while there are ways to ensure this doesn't happen with SQL, there's not much you can do with JavaScript.

As a trivial and useless example, a simplistic JavaScript calculator:

textbox1.value = eval(textbox2.value);

One correct usage examples are some of the JavaScript packers that compress JavaScript by pulling out common words and replacing them with short 1-2 character replacements. The packer then outputs all this along with string replacement code based on the dictionary generated then evals the result.

share|improve this answer
add comment

There are some things that are impossible to do in JS without an eval-like function (eval, Function, and maybe more).

Take apply for example. It is easy to use when using it on ordinary function calls:

foo.apply(null, [a, b, c])

But how would you do this for objects you are creating via new syntax?

new Foo.apply(null, [a, b, c]) doesn't work, nor do similar forms.

But you can work around this limitation via eval or Function (I use Function in this example):

Function.prototype.New = (function () {
    var fs = [];
    return function () {
        var f = fs[arguments.length];
        if (f) {
            return f.apply(this, arguments);
        }
        var argStrs = [];
        for (var i = 0; i < arguments.length; ++i) {
            argStrs.push("a[" + i + "]");
        }
        f = new Function("var a=arguments;return new this(" + argStrs.join() + ");");
        if (arguments.length < 100) {
            fs[arguments.length] = f;
        }
        return f.apply(this, arguments);
    };
}) ();

Example:

Foo.New.apply(null, [a, b, c]);

Of course, you could manually build the functions that Function.prototype.New uses, but not only is this verbose and clunky, it (by definition) has to be finite. Function allows the code to work for any number of arguments.

share|improve this answer
    
True, but the OP's question was "What are some improper uses of the Eval command, and what security holes do they open up?", not "What is a good use of eval()?" –  Ross Patterson Aug 14 '13 at 22:35
1  
@RossPatterson: Guess I mostly looked at the question's title haha. –  Thomas Eding Aug 14 '13 at 23:25
    
Still, +1 for finding a good use for a bad language feature :-) –  Ross Patterson Aug 15 '13 at 11:00
add comment

A somewhat direct answer on my part was developing a developer-oriented API-testing area. We gave a text area on a page, and a Run button. The central point of the page was for them to be able to try things out in Javascript against our iframe-communicating API that weren't so easy to do in a local environment.

Anything malicious that could have been done in that case could also have been done by the developer opening up their F12 tools.

share|improve this answer
add comment

I've seen it used well once or twice, but in general if there is any other possible way to do what you are doing, use that method!

share|improve this answer
add comment

I have a situation where eval looks like the way to go, evaluating a string and returning an existing variable whose name is the same as the string.

I have several tables: table1ResultsTable, table2ResultsTable, tableNResultsTable. I have variables set up with the same names, that are jQuery datatable objects. I use these to set up the tables and call jQuery datatable functions on them.

Each table has class="resultsTable" assigned. Now, I need to get the variable when the table is clicked. I'm doing this:

$('resultsTable).on('click', 'td', function(event) {
    var cResultsTable = eval(event.target.parentElement.parentElement.parentElement.id);
    [etc]
});

So I'm getting the id of the table in which the cell was clicked, which has the same name as the datatable object variable corresponding to it. If someone has a suggestion for an improvement I'd like to know about it.

share|improve this answer
1  
Why do you need eval? The id should be a plain string, not code. Anyhow, event.target.parentElement.parentElement.parentElement is horrific. Further, I'd expect the eval call to generate a "reference error: [id] is not defined" error, unless you're deliberately using evaluable ids (which is broken, wrong, and might cause weird things to happen if you end up generating duplicate ids). –  Brian Aug 14 '13 at 17:09
    
Perhaps I'm not making myself clear. The id IS a plain string. It's the id of the table that has been clicked. I also have an object variable (set with jQuery datatable() method, referencing the same table) with the same name as the id. I'm trying to get that variable, to access its functions (in fact, to add the "row_selected" class to the selected row), when the table is clicked. Since I wrote this, I've come up with an improvement, however. I just put all the object references in an array, name the elements the same as the id, and plug the id string into that to get the object ref. –  BobRodes Aug 14 '13 at 19:08
    
Brian, if you have a better means of finding the id of the table that has been clicked, I'm all ears. For the datatables function, I need to handle the click event against the cell, and add the row_selected class to its parentNode. Why I can't just handle the row event and add the class directly to it I don't know, but the row doesn't show as selected when I do that. –  BobRodes Aug 14 '13 at 19:09
    
Perhaps I'm not making myself clear. If you call eval on a plain (i.e., non-JS) string, you'll throw an exception. So, your use of eval doesn't make sense. If you happen to be generating an object variable with the same name as the id, your code will work...but strikes me as broken. I'd rather create the variable by using document.getElementById(ID).MySpecialProperty = MYSPECIALPROPERTYVALUE (not to say that's great either, but it's better than eval). As Eric Lippert points out, "every object in JScript already is a lookup table." –  Brian Aug 14 '13 at 19:12
    
Ok, so you're saying to add a property to the element reference and set it to the datatable object reference? That sounds tighter to me as well. –  BobRodes Aug 14 '13 at 20:14
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.