tonyg/js-nacl

eval used in library?

getify opened this issue · 9 comments

I have a CSP on my site which does not allow eval(), and trying to use nacl, I get errors thrown indicating the nacl library is trying to use it. What's the reason behind that? Is there anyway around it without just basically opening up a big hole in my CSP?

I've had a quick look: it looks like it's coming from the emscripten-generated portion of the code. Something to do with detecting which kind of environment the code is running in, for module-management purposes? I don't offhand know of a way in which it could be removed; perhaps you could check emscripten to see if there are any options that could be supplied to make it avoid using eval in this case, and rebuild the nacl module? Alternatively it might be possible to write a "stub" eval that answers only the questions asked by the nacl module. Some of the calls to eval are definitely stubbable like that; others, it's less clear.

I have faced similar issue in the past when compiling libgcrypt. The solution is to not use the closure compiler option to get rid of the eval() generated by emscripten.
So use --closure 0 in the Makefile instead of --closure 1

Hmm. Perhaps I need a newer emscripten: I just tried your recommendation, and the eval()s are still there. @getify, I don't have time right now to update my emscripten and try that; if you have a chance, perhaps you could give a new emscripten a go with @mnaamani's suggestion of --closure 0, and report back what you find?

(It wasn't a total loss, trying out the --closure 0 suggestion: omitting the closure-compilation step left this comment in the source, which gives a bit of context:

// The Module object: Our interface to the outside world. We import
// and export values on it, and do the work to get that through
// closure compiler if necessary. There are various ways Module can be used:
// 1. Not defined. We create it here
// 2. A function parameter, function(Module) { ..generated code.. }
// 3. pre-run appended it, var Module = {}; ..generated code..
// 4. External script tag defines var Module.
// We need to do an eval in order to handle the closure compiler
// case, where this code here is minified but Module was defined
// elsewhere (e.g. case 4 above). We also need to check if Module
// already exists (e.g. case 3 above).

)

I'm including this library in a chrome extension, and it is throwing and error message because of this same eval statement:

Uncaught EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'self' chrome-extension-resource:".
nacl_factory.js:15

Try https://github.com/cubicbase/ecma-nacl
It is hand-js. No eval. Much smaller. Simplier to audit and to compare with original NaCl.
If you do not need hash algorithms, as these are not done, as I personally didn't need them, yet.
Yet, for a packaged app (where size does not matter), js-nacl might be potentially faster, thus, desirable. Do comparison runs -- you might sometimes be surprised.
Trade-off, trade-offs ...

I have the same problem (same output as @tomwoods) in the Chrome App I'm developing. Any solutions found yet?

try the NO_DYNAMIC_EXECUTION flag

it helped me out

tonyg commented

js-nacl is now using libsodium, compiled using emscripten's emsdk v1.36. The newer emscripten output may have changed the situation regarding eval - it'd be worth another look!

tonyg commented

I'm fairly sure that no references to eval remain in the code (after a quick grep of the build output), so on the strength of that assumption, I'm going to close this. Please do reopen if it turns out still to be a problem!