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:
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().
Answer : You should use the 'new Function()' instead.
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!
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.
The most common uses which can be substituted are the following ones. I would certainly use these first.
Accessing dynamic properties
Do use: obj[keyAsVariable]
Don't use eval('obj.' + keyAsVariable)
Parsing JSON
Do use JSON.parse(data)
Don't use eval('(' + data + ')')
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'.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With