Estaba haciendo una calculadora que se sirve como una página html estática para el navegador del usuario. La página no está diseñada para enviar ninguna información al servidor. Nada más estará presente en la página web a excepción de esta calculadora.
¿Es seguro usar "eval" en este escenario? O dicho de otra manera, ¿el uso de eval en este caso genera un riesgo de seguridad adicional?
Para mí, no parece que el usuario pueda hacer nada nefasto con esta página que no pueda hacer simplemente abriendo las herramientas de desarrollo de los navegadores. Siempre he leído "nunca" use eval, pero en este caso, parece que tiene sentido.
Aquí hay una calculadora de ejemplo:
<!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>
Potencialmente abrirá la página a la ejecución de código arbitrario. Considere si alguien logra convencer a uno de sus usuarios o a algunos: "Intente pegar esto en el campo de entrada, ¡no podrá creer lo que sucederá a continuación!". Ese es un gran problema potencial si guarda datos relacionados con el usuario en el cliente, como credenciales de inicio de sesión en una cookie, o datos en Almacenamiento local o IndexedDB, etc.
Incluso si no almacena dichos datos, probablemente sería una buena idea desinfectar el valor de entrada para que solo contenga expresiones matemáticas y nada más. Por ejemplo, sería trivial permitir solo los números y operadores que desee, tal vez +-*/
. Es tan fácil de hacer y hace que las cosas sean seguras, así que deberías hacerlo.
Además, no coloque funciones en controladores en línea (ni use controladores en línea en absoluto), son una práctica bastante pobre. Adjunte detectores de eventos correctamente usando 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, '');
lo hace:
-
, +
, /
, *
\d
(cualquier dígito)