Search code examples
javascriptwebsecurity

Can eval() be made safe by pre-parsing the passed expression?


I understand at a high level why one would not want to allow arbitrary code to execute in a web browser via the JS eval() function.

But I wonder if there are any practical approaches to preventing attacks by parsing the code that is passed to eval() to check that it is safe. For example:

  • disallowing any flow control functions, e.g. for, while. (Should stop infinite loops)
  • disallowing any variable names / function calls that don't match a whitelist. (Should stop any access to the DOM, built-in APIs, or malicious functions)

If you don't think this can be done safely, could you describe the predicted pitfalls? It's valuable to me if somebody says "this isn't practical because X" rather than just some blanket statement. Trust me - if I can't convince myself with certainty that it can be done safely, I won't do it.

I know that I can write my own my expression evaluator or use a 3rd-party library that does the same. And I may do that. But I remain interested in using eval() because of certain advantages - native implementation performance and language consistency.


Solution

  • Yes, in general this is possible - basically you develop your own programming language that you know does only safe operations, you write your own parser for it, you write your own interpreter for it, and then you optimise that interpreter into a compiler targeting JavaScript that runs the result through eval.

    However, using JavaScript as the base language and then stripping away unsafe parts, or even whitelisting some things, is not a good approach. The "whitelisting" would need to be sophisticated enough that starting to develop your own language is generally simpler. The two example restriction you've presented in your question fail to reach their goals: to avoid infinite execution you also need to prevent recursion, and to prevent access to builtins you more or less also need to prevent dynamic property access. A lot of work has been done to define a proven "safe" subset of ECMAScript that one could fearlessly evaluate, and believe me, it is far from trivial.

    So no, this is not a practical approach.