0
var val = 3;

var code = "var a = 5; if (a >= val) { console.log(a + ' >= ' + val); a; } else { console.log(a + ' < 3 ' + val); val; }";


console.log(eval(code));


This is the scenario where an alternative to eval() is required. The Server can send any kind of JS code which could be run on a particular block.

Vignesh M
  • 85
  • 1
  • 9
  • Well, does it matter that that code is...weird? What's with the `a;` and the `val;` statements? At any rate, unless you parse the JS code yourself, you can't really execute it properly. And if you're parsing JS code, you might as well use `eval`. The solution seems to be fundamentally wrong - why would the server be generating JS code to send you? You'd normally define a function that does your logic and the server will send you the *parameters* for that. So you'd have the whole `if/else` in the function and supply `a` and `val` in this case. – VLAZ Oct 25 '18 at 06:25
  • @vlaz _"What's with the a; and the val; statements?"_ - those are output to the calling `console.log(eval(code));`. I think it's just example code. – Keith Oct 25 '18 at 12:27
  • Yes. Those a and val are the example code snippets. The real JS code will be a part of JSON as a string in certain keys which has to be executed on the front-end on certain scenarios. – Vignesh M Oct 26 '18 at 06:36
  • Is it ok to live with Eval() if we can assure that none of the code executed through eval is runtime. Everything is from the design time from the server??? – Vignesh M Oct 29 '18 at 03:59

3 Answers3

0

Do not use eval(code) or new Function(code) as both are basically the same thing and should be blocked by CSP.

Just return your content from the server as content-type: text/javascript then get it into your page with a <script> block or import.

On the server you would have something like (pseudo code, as I don't know what tech stack you're on):

[Route("serverActionReturningCode")]
public string ActionReturningCode() 
{
    // return the content as JS
    Response.Headers.Add("content-type", "text/javascript");

    // build the response object as JS
    return "window.latestResult = {" + 
        "a: '" + a + "', " +
        "b: '" + b + "', " + 
        "generatedCode: function() { ... }" + 
    "};";
}

Then in your page:

<script src="serverActionReturningCode"></script>
<script>
     // Now the script above has run and set window.latestResult
     console.log('a', window.latestResult.a);
     console.log('b', window.latestResult.b);
     console.log('function output', window.latestResult.generatedCode());
</script>

This will let you dynamically generate JS functions on the server.

However, if you can avoid the functions and just need to pass values it is a lot simpler to use JSON instead.

Keith
  • 150,284
  • 78
  • 298
  • 434
  • Actually, the server returns the JS code snippets within certain keys of JSON and we have to execute it on the front-end. – Vignesh M Oct 26 '18 at 06:38
  • @VigneshM Then if you want to avoid eval the server-generated script needs to set a variable, return something like this from the server `window.latestResult = { generatedCode: function() { ... } }` and then after that script block you can call `window.latestResult.generatedCode();` to execute it. – Keith Oct 26 '18 at 09:04
  • The value for the generatedCode is a function in your case. But, the JS code from the server will be a string right. Is there a way to parse the JS code which is obtained as a string? – Vignesh M Oct 29 '18 at 03:57
  • @VigneshM There's no safe way in the client JS to turn a string into executable code, _but_ to the server all the JS it returns is just strings. So the fix is for the server to return the string you want parsed as if it is just another `.js` file. – Keith Oct 29 '18 at 07:41
  • Is there any other JS parser or interpretter library or any other tool available to parse the JS code from the server via a JSON as a vector? – Vignesh M Oct 29 '18 at 07:47
  • If there is no other way for it, what will be the impact of living with eval assuring that the eval-ed code is completely generated in the design time of the user and not the runtime.? – Vignesh M Oct 29 '18 at 07:48
  • @VigneshM any JS that parses a JS string is going to be an XSS risk - it really should be blocked by [CSP](https://en.wikipedia.org/wiki/Content_Security_Policy). VeraCode (or any security audit) will always flag it up. However, when it comes from _your_ server you can make the whole response be Javascript - then it's just trusted. So, don't return a string from the server and then try to `eval` it, return JS from the server and run it directly. – Keith Oct 29 '18 at 12:49
0

It seems to be like there is no way other than to live with eval or change the entire design of the application. Even if we look for any other alternatives, it's going to be the change in the name and syntax. But the security issues are going to be the same. Its the design of the application that JS CodeGen tool in the server will generate JS code snippets and send it via JSON in certain fields which has to be picked and executed in the front-end. But in this design, we can assure one thing that the JS code is generated only at the design time of the user and not at the runtime. Thanks for your help.

Vignesh M
  • 85
  • 1
  • 9
  • You don't need to change the entire design of the application, you just need the server to return the executable JS directly. You can totally build run-time JS on the server, and if you need users to enter JS that you execute you can round-trip it (though I'd really avoid that unless you're trying to build something like the snippet builders on here). – Keith Oct 29 '18 at 12:57
-1

You can do it like this. Using Eval() is not recommended.

function looseJsonParse(obj){
    return Function('"use strict";return (' + obj + ')')();
}
console.log(looseJsonParse(
   "{a:(4-1), b:function(){}, c:new Date()}"
)) 

Refer this MDN article https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval to dig more into it.

rohitwtbs
  • 509
  • 5
  • 17
  • 1
    `new Function({string})` _is_ `eval` - it's not any better. – Keith Oct 25 '18 at 06:35
  • MDN says eval is slower. – rohitwtbs Oct 25 '18 at 06:42
  • You can cache the output with `Function`, so `var x = new Function('some code...'); x(); x();` will only do the code evaluation once, but execute it twice. A lot of early JS templating frameworks used this trick to optimise building components. So yeah, `Function` is quicker than `eval` for repeated calls, but the first call is the same and the security/XSS liability is still there. – Keith Oct 25 '18 at 10:44
  • I tried this way. But this seems to be much more dangerous than eval as the code is generated dynamically at the run time to give the access to the local variables to the new Function() ---
    --- let a = 5; let b = 3; let obj = 'console.log(window); console.log(this); return a+b;'; obj = "var a = " + a + "; var b = " + b + ";" + obj; console.log(Function(obj).call(this));
    – Vignesh M Oct 26 '18 at 06:43
  • Using this Function(), seems to increase the security issue as we need to dynamically generate JS code in the client side. – Vignesh M Oct 29 '18 at 03:58
  • Code generated at the runtime is more dangerous than the design time – Vignesh M Oct 29 '18 at 04:00