What are the security issues with "eval()" in JavaScript?
eval()
executes a string of characters as code. You use eval()
precisely because the string contents are not known in advance, or even generated server-side; basically, you need eval()
because the JavaScript itself will generate the string from data which is available only dynamically, in the client.
Thus, eval()
makes sense in situations where the JavaScript code will generate code. This is not intrinsically evil, but it is hard to do securely. Programming languages are designed to allow a human being to write instructions that a computer understands; to that effect, any language is full of small quirks and special behaviours that are supposed to help the human programmer (e.g. the automatic adding of ';' at the end of some statements in JavaScript). This is all nice and dandy for "normal" programming; but when you generate code from another program, based on data which may be potentially hostile (e.g. string excerpt from other site users), then you have to, as the developer for the code generator, know about all these quirks, and prevent hostile data to exploit them in damaging ways.
In that sense, code generators (and thus eval()
) incur the same conceptual issues as raw SQL and its consequence, SQL injection attacks. Assembling at runtime an SQL request from externally provided parameters can be done securely, but this requires minding an awful lot of details, so the usual advice is not to do that. This relates to the usual conundrum of security, i.e. that it is not testable: you can test whether some piece of code works properly on correct data, but not that it never works improperly on incorrect data. Similarly, using eval()
securely is possible, but it is so hard in practice that it is discouraged.
All of this is said in all generality. In your specific context, eval()
might be safe. However, it takes some effort to have a context safe for use of eval()
, that actually needs eval()
.
eval() is a possible vector for cross-site scripting.
Under normal circumstances, an attacker attempting XSS might want to get script <script></script>
tags past whatever encoding, filters or firewalls might be in place. If eval() is there operating on user input, it eliminates the need for script tags.
Eval is present in many malicious scripts because it helps obfuscate code and / or sneak prohibited characters past filters. For this reason, eval() is often checked for in user input. So, when using eval() you are, potentially, providing the attacker one of their necessary tools. I'm robbing a bank and I know I don't have to sneak a gun past any metal detectors because there are a bunch in the umbrella stand inside the building.
As explained by others, one can use eval to dynamically create code which makes it harder to understand the control flow of the program. But, I don't consider eval much more evil than all the other ways to generate code at run time, like document.write(...)
, object.innerHTML(...)
and others. While these are mostly used to change the DOM of the program they are also used to insert new code (i.e. add a script statement to the code, or a new element with some onXXXX handler etc).
And while eval is often used in attacks (XSS, malvertisement...) to circumvent filters or hide the real purpose of the code it is often used in an obfuscated form there, i.e. code like z='ev'; z+='al'; v=window; v[z]("alert(1)")
. This means you are not on the safe side if you simply try to filter code with explicit calls of eval, because either the call is obfuscated or "good" functions like innerHTML are used for bad purposes.