- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎04-05-2017 05:23 AM
Hi All,
There is a requirement related to service portal in which we have some piece of code getting generated dynamically based on user's selection. This dynamically generated code is client side code. This dynamically generated code comes up in string format when called from a UI Script. I need this code to be executed from UI Script. I have been searching for a solution for this from quite some time, but the only function I am able to get is eval(), which works perfectly in my scenario, however this is not recommended. GlideEvaluator is available but that runs server side.
Please let me know if anyone is aware of client side alternative to eval().
Thanks in advance!
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎04-05-2017 06:08 AM
Hi Astha,
The eval() function is a tool which is available because it meets a very specific need to evaluate javascript code dynamically when it's required. If there's an alternative to eval then it will have the same risks that eval has.
Eval is not evil, we just need to understand how it works and the risks of not employing it properly. There's an article that speaks into this. The article is so complete within the context of your question that I'll include it on this post as reference:
I hope this helps!
https://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/
eval() isn't evil, just misunderstood
Posted at June 25, 2013 by Nicholas C. Zakas
Tags: eval JavaScript
In all of JavaScript, I'm not sure there is a more maligned piece than
eval()
. This simple function designed to execute a string as JavaScript code has been the more source of more scrutiny and misunderstanding during the course of my career than nearly anything else. The phrase "eval() is evil" is most often attributed to Douglas Crockford, who has stated1:The
eval
function (and its relatives,Function
,setTimeout
, andsetInterval
) provide access to the JavaScript compiler. This is sometimes necessary, but in most cases it indicates the presence of extremely bad coding. Theeval
function is the most misused feature of JavaScript.Since Douglas hasn't put dates on most of his writings, it's unclear whether he actually coined the term as an article in 20032 also used this phrase without mentioning him. Regardless, it has become the go-to phrase for anyone who sees
eval()
in code, whether or not they really understand its use.Despite popular theory (and Crockford's insistence), the mere presence of
eval()
does not indicate a problem. Usingeval()
does not automatically open you up to a Cross-Site Scripting (XSS) attack nor does it mean there is some lingering security vulnerability that you're not aware of. Just like any tool, you need to know how to wield it correctly, but even if you use it incorrectly, the potential for damage is still fairly low and contained.
Misuse
At the time when "eval() is evil" originated, it was a source of frequent misuse by those who didn't understand JavaScript as a language. What may surprise you is that the misuse had nothing to do with performance or security, but rather with not understanding how to construct and use references in JavaScript. Suppose that you had several form inputs whose names contained a number, such as "option1″ and "option2″, it was common to see this:
function isChecked(optionNumber) { return eval("forms[0].option" + optionNumber + ".checked"); } var result = isChecked(1);
In this case, the developer is trying to write
forms[0].option1.checked
but is unaware of how to do that without usingeval()
. You see this sort of pattern a lot in code that is around ten years old or older as developers of that time just didn't understand how to use the language properly. The use ofeval()
is inappropriate here because it's unnecessary not because it's bad. You can easily rewrite this function as:function isChecked(optionNumber) { return forms[0]["option" + optionNumber].checked; } var result = isChecked(1);
In most cases of this nature, you can replace the call to
eval()
by using bracket notation to construct the property name (that is, after all, one reason it exists). Those early bloggers who talked about misuse, Crockford included, were mostly talking about this pattern.
Debugability
A good reason to avoid
eval()
is for debugging purposes. Until recently, it was impossible to step intoeval()
ed code if something went wrong. That meant you were running code into a black box and then out of it. Chrome Developer Tools can now debugeval()
ed code, but it's still painful. You have to wait until the code executes once before it shows up in the Source panel.Avoiding
eval()
ed code makes debugging easier, allowing you to view and step through the code easily. That doesn't makeeval()
evil, necessarily, just a bit problematic in a normal development workflow.
Performance
Another big hit against
eval()
is its performance impact. In older browsers, you encountered a double interpretation penalty, which is to say that your code is interpreted and the code inside ofeval()
is interpreted. The result could be ten times slower (or worse) in browsers without compiling JavaScript engines.With today's modern compiling JavaScript engines,
eval()
still poses a problem. Most engines can run code in one of two ways: fast path or slow path. Fast path code is code that is stable and predictable, and can therefore be compiled for faster execution. Slow path code is unpredictable, making it hard to compile and may still be run with an interpreter3. The mere presence ofeval()
in your code means that it is unpredictable and therefore will run in the interpreter — making it run at "old browser" speed instead of "new browser" speed (once again, a 10x difference).Also of note,
eval()
makes it impossible for YUI Compressor to munge variable names that are in scope of the call toeval()
. Sinceeval()
can access any of those variables directly, renaming them would introduce errors (other tools like Closure Compiler and UglifyJS may still munge those variables — ultimately causing errors).So performance is still a big concern when using
eval()
. Once again, that hardly makes it evil, but is a caveat to keep in mind.
Security
The trump card that many pull out when discussing
eval()
is security. Most frequently the conversation heads into the realm of XSS attacks and howeval()
opens up your code to them. On the surface, this confusion is understandable, since by its definitioneval()
executes arbitrary code in the context of the page. This can be dangerous if you're taking user input and running it througheval()
. However, if your input isn't from the user, is there any real danger?I've received more than one complaint from someone over a piece of code in my CSS parser that uses
eval()
4. The code in question useseval()
to convert a string token from CSS into a JavaScript string value. Short of creating my own string parser, this is the easiest way to get the true string value of the token. To date, no one has been able or willing to produce an attack scenario under which this code causes trouble because:
- The value being
eval()
ed comes from the tokenizer.- The tokenizer has already verified that it's a valid string.
- The code is most frequently run on the command line.
- Even when run in the browser, this code is enclosed in a closure and can't be called directly.
Of course, since this code has a primary destination of the command line, the story is a bit different.Code designed to be used in browsers face different issues, however, the security of
eval()
typically isn't one of them. Once again, if you are taking user input and passing it througheval()
in some way, then you are asking for trouble. Never ever do that. However, if your use ofeval()
has input that only you control and cannot be modified by the user, then there are no security risks.The most common attack vector cited these days is ineval()
ing code that is returned from the server. This pattern famously began with the introduction of JSON, which rose in popularity specifically because it could quickly be converted into a JavaScript by usingeval()
. Indeed, Douglas Crockford himself usedeval()
in his original JSON utility due to the speed with which it could be converted. He did add checks to make sure there was no truly executable code but the implementation was fundamentallyeval()
.These days, most use the built-in JSON parsing capabilities of browsers for this purpose, though some still fetch arbitrary JavaScript to execute viaeval()
as part of a lazy-loading strategy. This, some argue, is the real security vulnerability. If a man-in-the-middle attack is in progress, then you will be executing arbitrary attacker code on the page.The man-in-the-middle attack is wielded as the ever-present danger ofeval()
, opening the security can of worms. However, this is one scenario that doesn't concern me in the least, because anytime you can't trust the server you're contacting means any number of bad things are possible. Man-in-the-middle attacks can inject code onto the page in any number of ways:
- By returning attacker-controlled code for JavaScript loaded via
<script>
.- By returning attacker-controlled code for JSON-P requests.
- By returning attacker-controlled code from an Ajax request that is then
eval()
ed.Additionally, such an attack can easily steal cookies and user data without altering anything, let alone the possibility for phishing by returning attacker-controlled HTML and CSS.In short,
eval()
doesn't open you up to man-in-the-middle attacks any more than loading external JavaScript does. If you can't trust the code from your server then you have much bigger problems than aneval()
call here or there.
Conclusion
I'm not saying you should go run out and start using
eval()
everywhere. In fact, there are very few good use cases for runningeval()
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 whereeval()
makes sense. Try not using it first, but don't let anyone scare you into thinking your code is more fragile or less secure wheneval()
is used appropriately.
References
- About JSLint by Douglas Crockford (JSLint)
- Eval is evil, Part One by Eric Lippert (Eric's blog)
- Know Your Engines by David Mandelin (SlideShare)
- eval() usage in my CSS parser by me (GitHub)
Disclaimer: Any viewpoints and opinions expressed in this article are those of Nicholas C. Zakas and do not, in any way, reflect those of my employer, my colleagues, Wrox Publishing, O'Reilly Publishing, or anyone else. I speak only for myself, not for them.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎04-05-2017 06:08 AM
Hi Astha,
The eval() function is a tool which is available because it meets a very specific need to evaluate javascript code dynamically when it's required. If there's an alternative to eval then it will have the same risks that eval has.
Eval is not evil, we just need to understand how it works and the risks of not employing it properly. There's an article that speaks into this. The article is so complete within the context of your question that I'll include it on this post as reference:
I hope this helps!
https://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/
eval() isn't evil, just misunderstood
Posted at June 25, 2013 by Nicholas C. Zakas
Tags: eval JavaScript
In all of JavaScript, I'm not sure there is a more maligned piece than
eval()
. This simple function designed to execute a string as JavaScript code has been the more source of more scrutiny and misunderstanding during the course of my career than nearly anything else. The phrase "eval() is evil" is most often attributed to Douglas Crockford, who has stated1:The
eval
function (and its relatives,Function
,setTimeout
, andsetInterval
) provide access to the JavaScript compiler. This is sometimes necessary, but in most cases it indicates the presence of extremely bad coding. Theeval
function is the most misused feature of JavaScript.Since Douglas hasn't put dates on most of his writings, it's unclear whether he actually coined the term as an article in 20032 also used this phrase without mentioning him. Regardless, it has become the go-to phrase for anyone who sees
eval()
in code, whether or not they really understand its use.Despite popular theory (and Crockford's insistence), the mere presence of
eval()
does not indicate a problem. Usingeval()
does not automatically open you up to a Cross-Site Scripting (XSS) attack nor does it mean there is some lingering security vulnerability that you're not aware of. Just like any tool, you need to know how to wield it correctly, but even if you use it incorrectly, the potential for damage is still fairly low and contained.
Misuse
At the time when "eval() is evil" originated, it was a source of frequent misuse by those who didn't understand JavaScript as a language. What may surprise you is that the misuse had nothing to do with performance or security, but rather with not understanding how to construct and use references in JavaScript. Suppose that you had several form inputs whose names contained a number, such as "option1″ and "option2″, it was common to see this:
function isChecked(optionNumber) { return eval("forms[0].option" + optionNumber + ".checked"); } var result = isChecked(1);
In this case, the developer is trying to write
forms[0].option1.checked
but is unaware of how to do that without usingeval()
. You see this sort of pattern a lot in code that is around ten years old or older as developers of that time just didn't understand how to use the language properly. The use ofeval()
is inappropriate here because it's unnecessary not because it's bad. You can easily rewrite this function as:function isChecked(optionNumber) { return forms[0]["option" + optionNumber].checked; } var result = isChecked(1);
In most cases of this nature, you can replace the call to
eval()
by using bracket notation to construct the property name (that is, after all, one reason it exists). Those early bloggers who talked about misuse, Crockford included, were mostly talking about this pattern.
Debugability
A good reason to avoid
eval()
is for debugging purposes. Until recently, it was impossible to step intoeval()
ed code if something went wrong. That meant you were running code into a black box and then out of it. Chrome Developer Tools can now debugeval()
ed code, but it's still painful. You have to wait until the code executes once before it shows up in the Source panel.Avoiding
eval()
ed code makes debugging easier, allowing you to view and step through the code easily. That doesn't makeeval()
evil, necessarily, just a bit problematic in a normal development workflow.
Performance
Another big hit against
eval()
is its performance impact. In older browsers, you encountered a double interpretation penalty, which is to say that your code is interpreted and the code inside ofeval()
is interpreted. The result could be ten times slower (or worse) in browsers without compiling JavaScript engines.With today's modern compiling JavaScript engines,
eval()
still poses a problem. Most engines can run code in one of two ways: fast path or slow path. Fast path code is code that is stable and predictable, and can therefore be compiled for faster execution. Slow path code is unpredictable, making it hard to compile and may still be run with an interpreter3. The mere presence ofeval()
in your code means that it is unpredictable and therefore will run in the interpreter — making it run at "old browser" speed instead of "new browser" speed (once again, a 10x difference).Also of note,
eval()
makes it impossible for YUI Compressor to munge variable names that are in scope of the call toeval()
. Sinceeval()
can access any of those variables directly, renaming them would introduce errors (other tools like Closure Compiler and UglifyJS may still munge those variables — ultimately causing errors).So performance is still a big concern when using
eval()
. Once again, that hardly makes it evil, but is a caveat to keep in mind.
Security
The trump card that many pull out when discussing
eval()
is security. Most frequently the conversation heads into the realm of XSS attacks and howeval()
opens up your code to them. On the surface, this confusion is understandable, since by its definitioneval()
executes arbitrary code in the context of the page. This can be dangerous if you're taking user input and running it througheval()
. However, if your input isn't from the user, is there any real danger?I've received more than one complaint from someone over a piece of code in my CSS parser that uses
eval()
4. The code in question useseval()
to convert a string token from CSS into a JavaScript string value. Short of creating my own string parser, this is the easiest way to get the true string value of the token. To date, no one has been able or willing to produce an attack scenario under which this code causes trouble because:
- The value being
eval()
ed comes from the tokenizer.- The tokenizer has already verified that it's a valid string.
- The code is most frequently run on the command line.
- Even when run in the browser, this code is enclosed in a closure and can't be called directly.
Of course, since this code has a primary destination of the command line, the story is a bit different.Code designed to be used in browsers face different issues, however, the security of
eval()
typically isn't one of them. Once again, if you are taking user input and passing it througheval()
in some way, then you are asking for trouble. Never ever do that. However, if your use ofeval()
has input that only you control and cannot be modified by the user, then there are no security risks.The most common attack vector cited these days is ineval()
ing code that is returned from the server. This pattern famously began with the introduction of JSON, which rose in popularity specifically because it could quickly be converted into a JavaScript by usingeval()
. Indeed, Douglas Crockford himself usedeval()
in his original JSON utility due to the speed with which it could be converted. He did add checks to make sure there was no truly executable code but the implementation was fundamentallyeval()
.These days, most use the built-in JSON parsing capabilities of browsers for this purpose, though some still fetch arbitrary JavaScript to execute viaeval()
as part of a lazy-loading strategy. This, some argue, is the real security vulnerability. If a man-in-the-middle attack is in progress, then you will be executing arbitrary attacker code on the page.The man-in-the-middle attack is wielded as the ever-present danger ofeval()
, opening the security can of worms. However, this is one scenario that doesn't concern me in the least, because anytime you can't trust the server you're contacting means any number of bad things are possible. Man-in-the-middle attacks can inject code onto the page in any number of ways:
- By returning attacker-controlled code for JavaScript loaded via
<script>
.- By returning attacker-controlled code for JSON-P requests.
- By returning attacker-controlled code from an Ajax request that is then
eval()
ed.Additionally, such an attack can easily steal cookies and user data without altering anything, let alone the possibility for phishing by returning attacker-controlled HTML and CSS.In short,
eval()
doesn't open you up to man-in-the-middle attacks any more than loading external JavaScript does. If you can't trust the code from your server then you have much bigger problems than aneval()
call here or there.
Conclusion
I'm not saying you should go run out and start using
eval()
everywhere. In fact, there are very few good use cases for runningeval()
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 whereeval()
makes sense. Try not using it first, but don't let anyone scare you into thinking your code is more fragile or less secure wheneval()
is used appropriately.
References
- About JSLint by Douglas Crockford (JSLint)
- Eval is evil, Part One by Eric Lippert (Eric's blog)
- Know Your Engines by David Mandelin (SlideShare)
- eval() usage in my CSS parser by me (GitHub)
Disclaimer: Any viewpoints and opinions expressed in this article are those of Nicholas C. Zakas and do not, in any way, reflect those of my employer, my colleagues, Wrox Publishing, O'Reilly Publishing, or anyone else. I speak only for myself, not for them.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎04-05-2017 07:10 PM
Hi Berny,
Thanks a lot for this very informative Link!
I have gone through the article and could not find misuse of eval in my scenario.
Will get back in case there is anything else required.
Thanks & Regards,
Astha Chaubey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎04-05-2017 09:51 PM
Hi Astha
You're welcome! Actually... Kudos to you for asking this question! I really like the fact you preferred to ask and take an informed risk than just taking the chance.
Thanks,
Berny
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎04-05-2017 09:51 PM
On a less important note... would you mind marking the response as correct so that we can close this thread?
Thanks,
Berny