unsafe-eval security error in chrome extension #105

Closed
chinchang opened this Issue Aug 11, 2013 · 12 comments

Comments

Projects
None yet
3 participants

The error seems to be coming because of the following code:

f=Function("return this")()

Error:

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

Reduced case chrome extension: http://dl.dropboxusercontent.com/u/42214070/urijs-security-issue.crx

Owner

rodneyrehm commented Aug 11, 2013

I see the offending piece of code is generated through minification (Closure Compiler or UglifyJS2). This is (most likely) something I cannot fix within URI.js' source. Maybe you'll have to use the unminified code instead…

I see the same thing in the source as well: https://github.com/medialize/URI.js/blob/gh-pages/src/URI.js#L30

It could be changed to:

var root = (function(f){ return (function() { return this; })(); })();
Owner

rodneyrehm commented Aug 11, 2013

It's not that easy:

var root1 = (function(f){ return f('return this')(); })(Function);
var root2 = (function(f){ return (function() { return this; })(); })();
root1 === root2; // is false, because root2 is undefined.

Note: this is not the case if above code is run in the command line of your browser…

Owner

rodneyrehm commented Aug 11, 2013

Is the following also causing a SecurityError?

var root = (function(f){ return new f('return this')(); })(Function);

Still get the error.

About your above code:

var root1 = (function(f){ return f('return this')(); })(Function);
var root2 = (function(f){ return (function() { return this; })(); })();
root1 === root2;

Did you run it from within an IIFE and got false?

Owner

rodneyrehm commented Aug 11, 2013

(function(){
    var root1 = (function(f){ return f('return this')(); })(Function);
    var root2 = (function(f){ return (function() { return this; })(); })();
    root1 === root2; // is false
})();

if you run above code in the command line of your browser, you'll get true

Owner

rodneyrehm commented Aug 11, 2013

This problem was introduced with #84 - maybe @jasonkarns has an Idea how to circumvent this SecurityError?

Contributor

jasonkarns commented Aug 11, 2013

Hmm. I don't recall Chrome throwing that error at the time I encountered that snippet. Perhaps noConflict should be backed out until there's a workaround?

I've independently come to the conclusion that noConflict-style support is probably best handled by a micro-library, rather than natively within URI.js. Maybe it's just not worth it?

Owner

rodneyrehm commented Aug 11, 2013

To be fair, this SecurityError is thrown for Chrome Extensions - not the regular browser context.

I don't mind noConflict(). I'd like to keep it. After all, URI might eventually used by something native…

Accessing the global context seems to be the problem - is there no other way to safely get to it?

Contributor

jasonkarns commented Aug 12, 2013

So the purpose of noConflict is to allow users, when in a browser context, to safely include URI.js while controlling the impact it has on the global namespace. This is only a concern for non-module users. URI.js uses the UMD module definition pattern such that AMD or CommonJS users are already in control of the namespace footprint of URI.js. The UMD pattern already has access to the root object at the time the factory function is invoked. A possible solution is to modify the factory function to accept the root object as the last parameter. Or alternatively, execute the factory function in the context of the root object, thus giving the factory function access to the same root object as the UMD wrapper. Both solutions would remove the need for the pseudo-eval entirely.

Contributor

jasonkarns commented Aug 12, 2013

I just pushed up two branches to illustrate the two alternatives mentioned above. Neither has been tested.

A possible solution is to modify the factory function to accept the root object as the last parameter.

Quick and dirty implementation compared with master: jasonkarns/URI.js@medialize:master...root-factory-signature

Or alternatively, execute the factory function in the context of the root object, thus giving the factory function access to the same root object as the UMD wrapper.

Compared with master jasonkarns/URI.js@medialize:master...root-factory-context

Owner

rodneyrehm commented Aug 12, 2013

The issue is fixed in master and will be included in the next release

rodneyrehm closed this Aug 12, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment