browserify / static-eval

evaluate statically-analyzable expressions
MIT License
175 stars 27 forks source link

What is the different with this and eval? #26

Closed pdaddy26 closed 4 years ago

pdaddy26 commented 5 years ago

Hello,

Sorry if this is a silly question, but what would be the difference between this library and using eval or Function?

Also, what does statically-analyzable expressions mean?

Thanks,

goto-bus-stop commented 4 years ago

This library uses an AST to evaluate some types of code at build time. Statically-analyzable expressions are expressions that don't use any runtime variables.

var x = document.querySelectorAll('.some-class')

This is not a statically analyzable expression because document.querySelectorAll() depends on a runtime environment in a browser.

var x = a + 1

This may be a statically analyzable expression if a is known. For example, if we do:

staticEval(ast, {
  a: 1
})

then a is known to be 1, and a + 1 can be statically evaluated. But if we do

staticEval(ast)

the value of a is not known and the expression cannot be statically evaluated.

In general, the difference between static-eval and eval is that static-eval typically does not actually execute code. It looks at the code and figures out what the output would be if you ran it. (There is a caveat here that there are ways to "break out" of the static analysis by crafting malicious code, which is why we don't recommend this for security-sensitive applications.)

I hope that makes sense!

andrwo commented 4 years ago

I was just about to use this a static JS evaluator but did a double-take when I read your comment @goto-bus-stop (==> caveat here that there are ways to "break out" of the static analysis).

Now, i need some way to evaluate some JS against a (closed) context (no external variables, only pure functions), my JS depends on some user input so I can't guarantee sanitization, but I can't have security holes.

Can you just briefly let me know in what ways using this can be unsafe? I would have thought not relying on the V8 engine but parsing and running through the AST should be as safe as can be...

Thanks so much!

goto-bus-stop commented 4 years ago

Doing fully safe and robust AST evaluation basically requires you to implement a JS engine. static-eval implements a small subset of operations. in particular, it allows you to call functions: builtin functions like Math.min and function provided through options. the thing is that if you allow those function calls, someone can craft JS code that will access the prototype of those functions, which is the Function constructor, which is eval (real eval). There are many ways to do that, so while we've got checks in place to prevent some of those cases, it's likely that there are other undiscovered cases. static-eval was built for use in build pipelines on trusted code, so here it makes more sense to just explicitly be unsafe rather than try to plug all the holes forever :)

https://github.com/Agoric/ses-shim is intended to allow you to run untrusted code, so that might be a good place to look!

andrwo commented 4 years ago

Wasn't aware of ses-shim, thanks for the heads-up, and for the explanations! Much appreciated.