peterolson / BigInteger.js

An arbitrary length integer library for Javascript
The Unlicense
1.12k stars 187 forks source link

eval call breaks whole app if content-security-policy does not provide unsafe-eval #172

Closed skyboyer closed 5 years ago

skyboyer commented 5 years ago

I'm having project with BigInteger in dependencies. It's bundled with Webpack and deployed. Server returns header content-security-policy: default-src 'none'; .... script-src 'self'; .... and due to lacking 'unsafe-eval' script crashes with error message like

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'".

It's because of BigInteger.js#L651

    var pow;
    if (supportsNativeBigInt) {
        // forced to use eval because ** is a syntax error on pre-ECMAScript2017 environments.
        pow = eval("(a,b)=>a**b");
    }

I see the reason why it is made this way for lib code. But it is not always possible to make changes with content-security-policy.

v. 1.6.41

peterolson commented 5 years ago

Hmm, that's a problem. I can't think of any other way to take advantage of the native exponentiation without eval. (I've opened an issue on the tc39 repository to see if it's possible to work around it: https://github.com/tc39/proposal-bigint/issues/198)

The only option I can think of to fix this is to use the library's pow function instead of using the ** operator.

skyboyer commented 5 years ago

The same. Have realized just few ugly solutions(which I don't see acceptable anyway) like making two versions - with eval and with direct usage of exponential operator(but how to maintain both version? it's weird). Or using exponent operator without eval relying onto client project to use Babel's plugin for old env(but then what about using module with Node?).

I assumed there should be Babel plugin to search and remove blocks of code - so library users could set up Babel removing pre-marked block for case eval is forbidden. But have not found anything like that :(

Yaffle commented 5 years ago

Anothet ugly solutolion is to use try-catch block around eval. But this will fire the violation event anyway. There is no good way to detect if CSP is enabled from JavaScript.

peterolson commented 5 years ago

Resolved. I decided to use do the exponent through multiplication instead of using the ** operator.

I felt that the performance impact on the exponent operator was less important than the problems associated with eval.