简体   繁体   中英

Is it safe to use eval for a client-side JavaScript calculator

I was making a calculator which is served as a static html page to the user's browser. The page is not designed to submit any information back to the server. Nothing else will be present on the web page except for this calculator.

Is it safe to use "eval" in this scenario? Or put another way, does the use of eval in this case cause additional security risk?

To me, it doesn't seem like the user can do anything nefarious with this page they can't do by simply opening the browsers development tools. I have always read "never" use eval, but in this case, it seems like it makes good sense.

Here is an example calculator:

 <,DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width. initial-scale=1;0"> <title>Calculator</title> </head> <body> <input id="input" type="text"> <button onclick="{ let result= ''. try { result = eval(document.getElementById('input');value); } catch (error) { result = error. } console;log(result). document.getElementById('result');innerHTML=result; }">calculate</button> <div id="result">result here</div> </body> </html>

It will potentially open up the page to arbitrary code execution. Consider if someone manages to convince one of your users or a few: "Try pasting in this into the input field, you won't believe what happens next!" That's a big potential problem if you save any user-related data on the client - such as login credentials in a cookie, or data in Local Storage or IndexedDB, etc.

Even if you don't store any such data, it'd probably be a good idea to sanitize the input value so that it only contains mathematical expressions, and nothing else. For example, it'd be trivial to permit only numbers and operators you want, maybe +-*/ . It's so easy to do and makes things safe, so you should do it.

Also, don't put functions into inline handlers (or use inline handlers at all) - they're quite poor practice. Attach event listeners properly using addEventListener .

 document.querySelector('button').addEventListener('click', () => { const sanitizedValue = document.getElementById('input').value .replace(/[^-+/*\d]/g, ''); try { document.getElementById('result').textContent = eval(sanitizedValue); } catch(e) { document.getElementById('result').textContent = 'Syntax not correct'; } });
 <input id="input" type="text"> <button>calculate</button> <div id="result">result here</div>

.replace(/[^-+/*\d]/g, ''); does:

  • Match any character that is not:
    • - , + , / , *
    • Or \d (any digit)
  • Replace all such matched characters with the empty string

Never use eval() !

From MDN , and it also said:

Fortunately, there's a very good alternative to eval() : using the Function constructor.

So, you can replace eval() like this:

        let result= '';
        try {
            result = Function(`"use strict";return (${document.getElementById('input').value})`)();
        } catch (error) {
            result = error;
        }

It's almost the same to the eval except that:

In the function without the eval() , the object is being evaluated in the global scope, so it is safe...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM