Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alternatives for Javascript eval [duplicate]

Mozilla's Content Security Policy disallows the use of javascript eval function as well as inline scripts. They claim that all instances of eval can be replaced by another (hopefully safer) function. I agree in most scenarios, Javascript eval can be replaced, but I'm not sure whether the replacement is possible for every case.

My question is twofold:

  1. Is there a generic way to replace every javascript eval function? (doesn't have to be safe)
  2. Is there a case where the Javascript eval cannot be replaced?
like image 314
Tony Stark Avatar asked Aug 19 '11 21:08

Tony Stark


People also ask

What can I use instead of eval JavaScript?

An alternative to eval is Function() . Just like eval() , Function() takes some expression as a string for execution, except, rather than outputting the result directly, it returns an anonymous function to you that you can call. `Function() is a faster and more secure alternative to eval().

What should I use instead of eval?

Answer : You should use the 'new Function()' instead.

Why we should not use eval in JavaScript?

Malicious code : invoking eval can crash a computer. For example: if you use eval server-side and a mischievous user decides to use an infinite loop as their username. Terribly slow : the JavaScript language is designed to use the full gamut of JavaScript types (numbers, functions, objects, etc)… Not just strings!

What is wrong with eval ()?

Calling eval() will be slower than using alternatives, because it has to call JavaScript interpreter, which will convert evaluated code to the machine language. That means if you run the code more than once, the browser will have to interpret the same code again, which is highly inefficient.


2 Answers

The most common uses which can be substituted are the following ones. I would certainly use these first.

  1. Accessing dynamic properties

    Do use: obj[keyAsVariable]

    Don't use eval('obj.' + keyAsVariable)

  2. Parsing JSON

    Do use JSON.parse(data)

    Don't use eval('(' + data + ')')

  3. Calculating user input

    Do use a certain library

    Don't use eval(input)

If really necessary, you can also send the script to a server which simply echoes it back, and you can request it as a script tag. It won't use eval but still execute it. It isn't safe as it's sent twice over the Internet.

var s = document.createElement('script')
s.src = 'request_script?data=' + data;
document.getElementsByTagName('head')[0].appendChild(s);

request_script could be a file implemented in PHP, like the following. Again, it's bad practice but is a generic way of circumventing eval.

<?
echo $_GET['data'];
?>

You could say that this also automatically answers your second question with 'no'.

like image 157
pimvdb Avatar answered Oct 11 '22 05:10

pimvdb


Load as script using a Blob

Instead of using eval you can also use a Blob and load the code as if it was an external js file: To ensure that functions or variables that are inside the code that you are loading are available you need to use a callback method that will be triggered onload event.

var code = "console.log('hello world');";

// With eval:
eval(code);

// With a blob:
var blob = new Blob([code], {type: 'text/javascript'});
var urlCreator = window.URL || window.webkitURL;
var url = urlCreator.createObjectURL( blob );

function loadScript(url, callback)
{
    // Add a the script tag to the head
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;

    // Bind the callback (depends on browser compatibility).
    script.onreadystatechange = callback;
    script.onload = callback;

    // Load the script
    head.appendChild(script);
}

// Any variables or methods inside the code will be on callback.
loadScript(url, callback);

Note Be aware that the danger for code injection is similar to eval.

like image 41
Wilt Avatar answered Oct 11 '22 05:10

Wilt