eval in chrome package app

13,909

Solution 1

UPDATE:

Since at least January 2013, Chrome now permits the unsafe-eval Content Security Policy (CSP) directive, which allows eval execution outside of a sandbox:

The policy against eval() and its relatives like setTimeout(String), setInterval(String), and new Function(String) can be relaxed by adding 'unsafe-eval' to your policy

Add an appropriate CSP to you extension manifest, like:

"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"

The bug you refer to is now marked fixed, and has been included since Chrome 22.

Prior to the introduction of 'unsafe-eval', there was no way to have the CSP of a manifest_version: 2 extension allow execution of arbitrary text as code. At the time, Google made it clear there was no way to remove this restriction (outside of sandboxing):

Inline JavaScript, as well as dangerous string-to-JavaScript methods like eval, will not be executed... There is no mechanism for relaxing the restriction against executing inline JavaScript. In particular, setting a script policy that includes unsafe-inline will have no effect. This is intentional.

As mentioned above, this restriction can now be relaxed.

Solution 2

I suppose you are talking about the new packaged app (manifest version 2), right?

Sandboxes can be used in the new packaged apps, absolutely. Last week I just uploaded a sample which does exactly that: A window sends a message to a hidden sandboxed iframe, the iframe compiles a handlebar template (here it could use eval instead) and returns the compiled HTML to the hosting page, which shows the result.

You can also check this other sample, which does exactly what you want.

So, to directly answer your questions:

1) No, because of CSP restrictions. The only way to evaluate dynamic JavaScript in Chrome Packaged Apps is the sandboxed iframe. If that's not an option to your app, you could also send and evaluate the JavaScript content in your server and return only the results to the user (although this breaks the offline feature of Chrome Packaged Apps)

2) No, you can only use eval() in a sandboxed iframe.

Solution 3

You could use : $scope.$eval() from angular.

Solution 4

I came to this answer after an Angular.js chrome app I was starting gave the same error. The author did not mention Angular.js but if anyone else comes across this you need to add an additional directive to your web page e.g.

<html ng-app ng-csp>
...

This puts angular in CSP-safe mode https://docs.angularjs.org/api/ng/directive/ngCsp

Solution 5

You could try...

function evalMe(code){
    var script = document.createElement('script');
    script.innerText = code;
    document.querySelector('head').appendChild(script);
}

This should create the same effect, unless they have disabled it as well, but from my knowledge this is fine. Of course if the script errors you will not hear about it unless you do some wrapping of the string to eval e.g.

function myHandler(err){
    // handle errors.   
}

function evalMe(code){
    var script = document.createElement('script');
    var wrapper = '(function(){ try{ @@ }catch(err){ myHandler(err); } })()';
    // Make sure the string has an ending semicolon
    code = code[code.length-1] === ';' ? code : code + ';';

    script.innerText = wrapper.replace('@@', code);
    document.querySelector('head').appendChild(script);
}

Alternately you could use the official mechanism

http://developer.chrome.com/beta/extensions/tabs.html#method-executeScript

However this would require you to have a background page and employ message passing between your app page and the background page.

UPDATE: Working Method

You can create an eval like method using an iframe and a base64 encoded dataURI that handles message passing between the extension page and the <iframe>. You can grab a working copy of the code on github. To use simply clone or download the repo, and install the 'client' dir as an unpackaged extension in the chrome extension manager. The code driving the plugin resides in app.js

Use the iframeEval to test, the error notification is a little buggy but hey, the eval works.

@appsillers In order to get your plugin working without any additional code, you could overwrite the eval method on you extensions window with the iframeEval method in the code.

Share:
13,909

Related videos on Youtube

Charles
Author by

Charles

I'm software developer. Currently working for Pidoco°.

Updated on June 15, 2022

Comments

  • Charles
    Charles almost 2 years

    I would like to create a package app chrome extension to allow the user to write and execute javascript code (like a javascript console).

    I would like to use the eval() function to execute the JS code.

    The classic javascript eval function throws an error when it's called from a chrome extension:

    Uncaught Error: Code generation from strings disallowed for this context

    To use eval in a chrome extension people need to use a sandbox, but when I write the sandbox in the manifest I get this error:

    There were warnings when trying to install this extension: 'sandbox' is not allowed for specified package type (theme, app, etc.).

    UPDATE

    According to this issue, sandboxes are not supported for package apps, so I have two questions:

    1. Is there another method which I can use instead of eval()?

    2. Is it possible to use eval without a sandbox? (I think probably not for security reasons?)

    • apsillers
      apsillers over 11 years
      I don't know much about it, but using js.js might be a possible (albeit performance-inferior) solution.
  • Charles
    Charles over 11 years
    thanks, but same problem: Uncaught Error: Code generation from strings disallowed for this context
  • elclanrs
    elclanrs over 11 years
    Don't know... Yout might be right, maybe it's a security issue and they disabled it.
  • Wladimir Palant
    Wladimir Palant over 11 years
    Content Security Policy disallows any kind of dynamic code generation in Chrome extensions - be it eval() or new Function().
  • apsillers
    apsillers over 11 years
    manifest_version: 2 disallows inline scripts, so I expect evalMe would produce an error because it injects a <script> with an inline script. Your final suggestion about passing a message to perform an executeScript in the background is an interesting possibility, but I think it may be constrained to a separate execution environment, as background pages are. I'll test to see if that is correct.
  • apsillers
    apsillers over 11 years
    I just tested my first point, and evalMe produces the error Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' chrome-extension-resource:".
  • AshHeskes
    AshHeskes over 11 years
    hmm, let me do some more digging in the docs. As a question, are the evaluated scripts requiring access to the pages DOM? or are they pure.js
  • AshHeskes
    AshHeskes over 11 years
    I'm assuming not, otherwise eval would would be pretty dangerous as your giving eval'ed code permission to access chrome API's. Unless this is your intention
  • jamesmortensen
    jamesmortensen over 11 years
    Here's a link to the docs on this, which shows examples demonstrating that any string evaluation of JavaScript is not supported. developer.chrome.com/extensions/contentSecurityPolicy.html. Consider making an edit to your post to correct the inaccuracies, or consider its removal. Good luck! :)
  • jamesmortensen
    jamesmortensen over 11 years
    ok, so I thought your post was a good example of what will not work, and the fact that this is here does clear up a few points about exactly how far Google is willing to go to keep us safe ;), so I edited your post to make it correct and still useful to future visitors, preserving the core of your answer. Hope this helps! +1
  • Rob W
    Rob W almost 11 years
    You could update your answer to mention the unsafe-eval directive, developer.chrome.com/extensions/…
  • Jason Kim
    Jason Kim over 10 years
    Make sure you reload the extension after you add this in the manifest.json.
  • Patricia Garcia
    Patricia Garcia over 9 years
    I just want to add that this method only works for extensions, not packaged apps (since the title of the thread refers to packaged apps).
  • apsillers
    apsillers over 9 years
    @PatriciaGarcia Interesting, yes -- the confusion here seems to be that the term "packaged app" refers to two very different things, and the OP's linked bug report refers to "legacy packaged apps" which basically are extensions with an app-screen icon. However, it's likely that the OP didn't realize this about the bug report (neither did I), and actually means modern packaged apps. Thanks for pointing this out; I'll see if I can make the effort to clarify this answer shortly.
  • asdjfiasd
    asdjfiasd about 9 years
    Both links are broken
  • mangini
    mangini about 9 years
    Fixed. The Github repository has been refactored, which caused the invalid URLs.
  • YakovL
    YakovL almost 8 years
    Welcome to StackOverflow. You should probably elaborate your question to some extent: have you tested this or do you have some experience, or just threw an idea that came to your mind? Although the latter may be ok, too, more elaborate answers are more welcome. Also, please use code wrappers. Best regards.