Why is using the JavaScript eval function a bad idea?

JavascriptSecurityEval

Javascript Problem Overview


The eval function is a powerful and easy way to dynamically generate code, so what are the caveats?

Javascript Solutions


Solution 1 - Javascript

  1. Improper use of eval opens up your code for injection attacks

  2. Debugging can be more challenging (no line numbers, etc.)

  3. eval'd code executes slower (no opportunity to compile/cache eval'd code)

Edit: As @Jeff Walden points out in comments, #3 is less true today than it was in 2008. However, while some caching of compiled scripts may happen this will only be limited to scripts that are eval'd repeated with no modification. A more likely scenario is that you are eval'ing scripts that have undergone slight modification each time and as such could not be cached. Let's just say that SOME eval'd code executes more slowly.

Solution 2 - Javascript

eval isn't always evil. There are times where it's perfectly appropriate.

However, eval is currently and historically massively over-used by people who don't know what they're doing. That includes people writing JavaScript tutorials, unfortunately, and in some cases this can indeed have security consequences - or, more often, simple bugs. So the more we can do to throw a question mark over eval, the better. Any time you use eval you need to sanity-check what you're doing, because chances are you could be doing it a better, safer, cleaner way.

To give an all-too-typical example, to set the colour of an element with an id stored in the variable 'potato':

eval('document.' + potato + '.style.color = "red"');

If the authors of the kind of code above had a clue about the basics of how JavaScript objects work, they'd have realised that square brackets can be used instead of literal dot-names, obviating the need for eval:

document[potato].style.color = 'red';

...which is much easier to read as well as less potentially buggy.

(But then, someone who /really/ knew what they were doing would say:

document.getElementById(potato).style.color = 'red';

which is more reliable than the dodgy old trick of accessing DOM elements straight out of the document object.)

Solution 3 - Javascript

I believe it's because it can execute any JavaScript function from a string. Using it makes it easier for people to inject rogue code into the application.

Solution 4 - Javascript

Two points come to mind:

  1. Security (but as long as you generate the string to be evaluated yourself, this might be a non-issue)

  2. Performance: until the code to be executed is unknown, it cannot be optimized. (about javascript and performance, certainly Steve Yegge's presentation)

Solution 5 - Javascript

It's generally only an issue if you're passing eval user input.

Solution 6 - Javascript

Passing user input to eval() is a security risk, but also each invocation of eval() creates a new instance of the JavaScript interpreter. This can be a resource hog.

Solution 7 - Javascript

Mainly, it's a lot harder to maintain and debug. It's like a goto. You can use it, but it makes it harder to find problems and harder on the people who may need to make changes later.

Solution 8 - Javascript

One thing to keep in mind is that you can often use eval() to execute code in an otherwise restricted environment - social networking sites that block specific JavaScript functions can sometimes be fooled by breaking them up in an eval block -

eval('al' + 'er' + 't(\'' + 'hi there!' + '\')');

So if you're looking to run some JavaScript code where it might not otherwise be allowed (Myspace, I'm looking at you...) then eval() can be a useful trick.

However, for all the reasons mentioned above, you shouldn't use it for your own code, where you have complete control - it's just not necessary, and better-off relegated to the 'tricky JavaScript hacks' shelf.

Solution 9 - Javascript

Unless you let eval() a dynamic content (through cgi or input), it is as safe and solid as all other JavaScript in your page.

Solution 10 - Javascript

Along with the rest of the answers, I don't think eval statements can have advanced minimization.

Solution 11 - Javascript

It is a possible security risk, it has a different scope of execution, and is quite inefficient, as it creates an entirely new scripting environment for the execution of the code. See here for some more info: eval.

It is quite useful, though, and used with moderation can add a lot of good functionality.

Solution 12 - Javascript

Unless you are 100% sure that the code being evaluated is from a trusted source (usually your own application) then it's a surefire way of exposing your system to a cross-site scripting attack.

Solution 13 - Javascript

It's not necessarily that bad provided you know what context you're using it in.

If your application is using eval() to create an object from some JSON which has come back from an XMLHttpRequest to your own site, created by your trusted server-side code, it's probably not a problem.

Untrusted client-side JavaScript code can't do that much anyway. Provided the thing you're executing eval() on has come from a reasonable source, you're fine.

Solution 14 - Javascript

It greatly reduces your level of confidence about security.

Solution 15 - Javascript

If you want the user to input some logical functions and evaluate for AND the OR then the JavaScript eval function is perfect. I can accept two strings and eval(uate) string1 === string2, etc.

Solution 16 - Javascript

If you spot the use of eval() in your code, remember the mantra “eval() is evil.”

This function takes an arbitrary string and executes it as JavaScript code. When the code in question is known beforehand (not determined at runtime), there’s no reason to use eval(). If the code is dynamically generated at runtime, there’s often a better way to achieve the goal without eval(). For example, just using square bracket notation to access dynamic properties is better and simpler:

// antipattern
var property = "name";
alert(eval("obj." + property));

// preferred
var property = "name";
alert(obj[property]);

Using eval() also has security implications, because you might be executing code (for example coming from the network) that has been tampered with. This is a common antipattern when dealing with a JSON response from an Ajax request. In those cases it’s better to use the browsers’ built-in methods to parse the JSON response to make sure it’s safe and valid. For browsers that don’t support JSON.parse() natively, you can use a library from JSON.org.

It’s also important to remember that passing strings to setInterval(), setTimeout(), and the Function() constructor is, for the most part, similar to using eval() and therefore should be avoided.

Behind the scenes, JavaScript still has to evaluate and execute the string you pass as programming code:

// antipatterns
setTimeout("myFunc()", 1000);
setTimeout("myFunc(1, 2, 3)", 1000);

// preferred
setTimeout(myFunc, 1000);
setTimeout(function () {
myFunc(1, 2, 3);
}, 1000);

Using the new Function() constructor is similar to eval() and should be approached with care. It could be a powerful construct but is often misused. If you absolutely must use eval(), you can consider using new Function() instead.

There is a small potential benefit because the code evaluated in new Function() will be running in a local function scope, so any variables defined with var in the code being evaluated will not become globals automatically.

Another way to prevent automatic globals is to wrap the eval() call into an immediate function.

Solution 17 - Javascript

Besides the possible security issues if you are executing user-submitted code, most of the time there's a better way that doesn't involve re-parsing the code every time it's executed. Anonymous functions or object properties can replace most uses of eval and are much safer and faster.

Solution 18 - Javascript

This may become more of an issue as the next generation of browsers come out with some flavor of a JavaScript compiler. Code executed via Eval may not perform as well as the rest of your JavaScript against these newer browsers. Someone should do some profiling.

Solution 19 - Javascript

This is one of good articles talking about eval and how it is not an evil: http://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/

> I’m not saying you should go run out and start using eval() > everywhere. In fact, there are very few good use cases for running > eval() at all. There are definitely concerns with code clarity, > debugability, and certainly performance that should not be overlooked. > But you shouldn’t be afraid to use it when you have a case where > eval() makes sense. Try not using it first, but don’t let anyone scare > you into thinking your code is more fragile or less secure when eval() > is used appropriately.

Solution 20 - Javascript

eval() is very powerful and can be used to execute a JS statement or evaluate an expression. But the question isn't about the uses of eval() but lets just say some how the string you running with eval() is affected by a malicious party. At the end you will be running malicious code. With power comes great responsibility. So use it wisely is you are using it. This isn't related much to eval() function but this article has pretty good information: <http://blogs.popart.com/2009/07/javascript-injection-attacks/> If you are looking for the basics of eval() look here: <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval>

Solution 21 - Javascript

The JavaScript Engine has a number of performance optimizations that it performs during the compilation phase. Some of these boil down to being able to essentially statically analyze the code as it lexes, and pre-determine where all the variable and function declarations are, so that it takes less effort to resolve identifiers during execution.

But if the Engine finds an eval(..) in the code, it essentially has to assume that all its awareness of identifier location may be invalid, because it cannot know at lexing time exactly what code you may pass to eval(..) to modify the lexical scope, or the contents of the object you may pass to with to create a new lexical scope to be consulted.

In other words, in the pessimistic sense, most of those optimizations it would make are pointless if eval(..) is present, so it simply doesn't perform the optimizations at all.

This explains it all.

Reference :

https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#eval

https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#performance

Solution 22 - Javascript

It's not always a bad idea. Take for example, code generation. I recently wrote a library called Hyperbars which bridges the gap between virtual-dom and handlebars. It does this by parsing a handlebars template and converting it to hyperscript which is subsequently used by virtual-dom. The hyperscript is generated as a string first and before returning it, eval() it to turn it into executable code. I have found eval() in this particular situation the exact opposite of evil.

Basically from

<div>
    {{#each names}}
        <span>{{this}}</span>
    {{/each}}
</div>

To this

(function (state) {
    var Runtime = Hyperbars.Runtime;
    var context = state;
    return h('div', {}, [Runtime.each(context['names'], context, function (context, parent, options) {
	    return [h('span', {}, [options['@index'], context])]
    })])
}.bind({}))

The performance of eval() isn't an issue in a situation like this because you only need to interpret the generated string once and then reuse the executable output many times over.

You can see how the code generation was achieved if you're curious here.

Solution 23 - Javascript

I would go as far as to say that it doesn't really matter if you use eval() in javascript which is run in browsers.*(caveat)

All modern browsers have a developer console where you can execute arbitrary javascript anyway and any semi-smart developer can look at your JS source and put whatever bits of it they need to into the dev console to do what they wish.

*As long as your server endpoints have the correct validation & sanitisation of user supplied values, it should not matter what gets parsed and eval'd in your client side javascript.

If you were to ask if it's suitable to use eval() in PHP however, the answer is NO, unless you whitelist any values which may be passed to your eval statement.

Solution 24 - Javascript

Garbage collection

The browsers garbage collection has no idea if the code that's eval'ed can be removed from memory so it just keeps it stored until the page is reloaded. Not too bad if your users are only on your page shortly, but it can be a problem for webapp's.

Here's a script to demo the problem

https://jsfiddle.net/CynderRnAsh/qux1osnw/

document.getElementById("evalLeak").onclick = (e) => {
  for(let x = 0; x < 100; x++) {
    eval(x.toString());
  }
};

Something as simple as the above code causes a small amount of memory to be store until the app dies. This is worse when the evaled script is a giant function, and called on interval.

Solution 25 - Javascript

I won't attempt to refute anything said heretofore, but i will offer this use of eval() that (as far as I know) can't be done any other way. There's probably other ways to code this, and probably ways to optimize it, but this is done longhand and without any bells and whistles for clarity sake to illustrate a use of eval that really doesn't have any other alternatives. That is: dynamical (or more accurately) programmically-created object names (as opposed to values).

//Place this in a common/global JS lib:
var NS = function(namespace){
    var namespaceParts = String(namespace).split(".");
    var namespaceToTest = "";
    for(var i = 0; i < namespaceParts.length; i++){
	    if(i === 0){
			namespaceToTest = namespaceParts[i];
		}
		else{
			namespaceToTest = namespaceToTest + "." + namespaceParts[i];
		}

		if(eval('typeof ' + namespaceToTest) === "undefined"){
			eval(namespaceToTest + ' = {}');
		}
	}
	return eval(namespace);
}


//Then, use this in your class definition libs:
NS('Root.Namespace').Class = function(settings){
  //Class constructor code here
}
//some generic method:
Root.Namespace.Class.prototype.Method = function(args){
	//Code goes here
	//this.MyOtherMethod("foo"));  // => "foo"
	return true;
}


//Then, in your applications, use this to instantiate an instance of your class:
var anInstanceOfClass = new Root.Namespace.Class(settings);

EDIT: by the way, I wouldn't suggest (for all the security reasons pointed out heretofore) that you base you object names on user input. I can't imagine any good reason you'd want to do that though. Still, thought I'd point it out that it wouldn't be a good idea :)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBrian SinghView Question on Stackoverflow
Solution 1 - JavascriptPrestaulView Answer on Stackoverflow
Solution 2 - JavascriptbobinceView Answer on Stackoverflow
Solution 3 - Javascriptkemiller2002View Answer on Stackoverflow
Solution 4 - JavascriptxtoflView Answer on Stackoverflow
Solution 5 - JavascriptMark BiekView Answer on Stackoverflow
Solution 6 - JavascriptAndrew HedgesView Answer on Stackoverflow
Solution 7 - JavascriptBrianView Answer on Stackoverflow
Solution 8 - Javascriptmatt lohkampView Answer on Stackoverflow
Solution 9 - JavascriptThevsView Answer on Stackoverflow
Solution 10 - JavascriptPaul MendozaView Answer on Stackoverflow
Solution 11 - JavascriptTomView Answer on Stackoverflow
Solution 12 - JavascriptJohn TopleyView Answer on Stackoverflow
Solution 13 - JavascriptMarkRView Answer on Stackoverflow
Solution 14 - JavascriptDavid PlumptonView Answer on Stackoverflow
Solution 15 - JavascriptIanView Answer on Stackoverflow
Solution 16 - Javascript12345678View Answer on Stackoverflow
Solution 17 - JavascriptMatthew CrumleyView Answer on Stackoverflow
Solution 18 - JavascriptBrianView Answer on Stackoverflow
Solution 19 - JavascriptAmr ElgarhyView Answer on Stackoverflow
Solution 20 - JavascriptPhiView Answer on Stackoverflow
Solution 21 - JavascripthkaseraView Answer on Stackoverflow
Solution 22 - JavascriptWikenedView Answer on Stackoverflow
Solution 23 - JavascriptAdam CopleyView Answer on Stackoverflow
Solution 24 - JavascriptJ DView Answer on Stackoverflow
Solution 25 - JavascriptCarnixView Answer on Stackoverflow