18

Github has the following Content Security Policy:

Content-Security-Policy:default-src *; script-src assets-cdn.github.com www.google-analytics.com collector-cdn.github.com; object-src assets-cdn.github.com; style-src 'self' 'unsafe-inline' 'unsafe-eval' assets-cdn.github.com; img-src 'self' data: assets-cdn.github.com identicons.github.com www.google-analytics.com collector.githubapp.com *.githubusercontent.com *.gravatar.com *.wp.com; media-src 'none'; frame-src 'self' render.githubusercontent.com www.youtube.com player.vimeo.com checkout.paypal.com; font-src assets-cdn.github.com; connect-src 'self' ghconduit.com:25035 live.github.com uploads.github.com s3.amazonaws.com

We can clip/retrieve content from the web with browser extensions of services likes Evernote or Pocket.

I don't see any reference to Pocket or Evernote in this Github policy. Can someone please explain why the Pocket extension is able to retrieve content from Github, while the Evernote extension is not, having a CSP error)

Can the CSP policy prevent a bookmarklet app or a browser extension app like a clipper to load? If so, how Pocket does to be able make their extension work on any content?

We have this problem in our bookmarklets/extensions and I would like them to work as smooth as Pocket extension but I don't really know where to start... thanks


Edit: As people are asking for code in the comments, our bookmarklet is loaded with this javascript:

javascript: (function() {
    function loadScript(a, b) {
        var c = document.createElement('script');
        c.type = 'text/javascript';
        c.src = a;
        var d = document.getElementsByTagName('head')[0],
            done = false;
        c.onload = c.onreadystatechange = function() {
            if (!done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')) {
                done = true;
                b()
            }
        };
        d.appendChild(c)
    }
    loadScript('http://localhostsss.com:9000/assets/js/backbone/views/clipping/clippinglocal.js', function() {
        s.clipping.initClipping()
    })
})()

If I try to launch this bookmarklet in a Medium page, which have a CSP, I get the following error.

Refused to load the script 'http://localhostssss.com:9000/assets/js/backbone/views/clipping/clippinglocal.js' because it violates the following Content Security Policy directive: "script-src 'unsafe-eval' 'unsafe-inline' about: https://.akamaihd.net http://.baidu.com https://bitly.com https://.cloudfront.net https://.facebook.com https://.facebook.net https://getpocket.com https://.github.com https://.googleapis.com https://ssl.google-analytics.com https://app.greenhouse.io https://.medium.com https://myspace.com https://.pinterest.com https://www.readability.com https://thinkery.me https://this.cm https://.twitter.com https://use.typekit.net https://*.instapaper.com 'self'".

Can someone tell me how to make our bookmarklet loadable on websites like Medium or Github which have a CSP policy.

I can't talk so much about browser extensions yet because I didn't work on it yet and the person is not here atm. I just know that we have the same problem and our browser extensions are basically the same code as our bookmarklets except it's a little bit adapted to fit in a browser extension shell. If you can only answer for the bookmarklet case I'll be ok and accept the answer but any hint for browser extensions would be nice too :)

Sebastien Lorber
  • 79,294
  • 59
  • 260
  • 386
  • Can I please ask for a bit more context? Is this a question about a github app or web page? Is the problem with evernote a problem with an evernote app or web page? If it is a problem with the github app, and you wish to allow your app to communicate with the evernote web site, you would need to add permissions in your manifest.json. – petewil-G Aug 27 '14 at 16:54
  • @petewil-G we are developping a clipper like Evernote/Pocket, and we need to be able to clip content on sites with CSP policies (like Github or Medium). We have both a bookmarklet and browser extensions (`manifest.json` does not apply to bookmarklets I think) – Sebastien Lorber Aug 27 '14 at 17:11
  • Please remove the google-chrome-app tag, as this question has nothing to do with Chrome Apps. – Marc Rochkind Aug 27 '14 at 20:51
  • This question needs improvement. You take a long time to say what you want to do is possible, but spend no time discussing your own code. Post a code sample that demonstrates the thing you think should work, then ask us why it doesn't work. – sowbug Aug 27 '14 at 22:37
  • @sowbug I added the code to load our bookmarklet – Sebastien Lorber Aug 28 '14 at 09:24
  • 1. Host your script over `https://******.github.com`, *it will probably be served as `text/plain`*, inject a simple `$.ajax(...)` method to fetch the text-content, then create a new ` –  Nov 27 '15 at 23:24

1 Answers1

17

Can the CSP policy prevent a bookmarklet app or a browser extension app like a clipper to load?

It is very simple: The extension or bookmarklet will be blocked if it violates the CSP.

So, if the CSP blocks all inline script, no bookmarklet will work. Github does that with media-src because, by simply existing, the "media-src" directive blocks inline script by default. So no bookmarklet can work on Github.

(As a side note, even though all browsers work this way, this isn't what the standards says should happen. Bookmarklets should actually exempt from CSP, but unfortunately no browsers have bothered to permit that.)

Now, as for which extensions will work or will not work, that depends on how the extension itself works. Extensions can not be directly blocked by CSP, but, if the extension tries to do anything which does violates the CSP, it may fail. So, on Github, if the extension tries to add native script into the page's DOM, or tries to append an external script to the page's DOM from an unapproved location, or do any of the other restricted things described in the CSP, it may fail.

So, what part of the Evernote extension is causing a CSP error and how does Pocket do a similar job without causing an error? I don't know. That all depends on the very specific details of how those applications are written. Most likely it is quite simple to look at their code and try to figure it out. As far as I know, all Chrome extensions are written in JavaScript and packaged as a zip file - just with a different file extension. I believe that the same is true of Firefox addons also.

DG.
  • 3,137
  • 2
  • 17
  • 27
  • 1
    thanks for your insight. How do you know that bookmarklets should exempt from CSP and browsers did not implemented that? are there issues opened on browsers for that? – Sebastien Lorber Aug 28 '14 at 09:31
  • do you think our extension does not work because it actually doesn't contain the whole app code but tries to load the code from a remote url? This means that we probably need to package all the extension code in the same zip file instead of loading it remotely I guess. – Sebastien Lorber Aug 28 '14 at 09:33
  • As you found, there is an issue open for Chrome and I've seen one for Firefox. Unfortunately I doubt it is going to be fixed anytime soon though, if ever, because the solution would probably be complex. I don't see it becoming a priority for the browser developers. – DG. Aug 28 '14 at 16:17
  • Unfortunately (in the rage inducing sort of way) it sounds like for the moment there is "no solution" if your code is too big to pack into a bookmarklet. :-( – Michael Dec 30 '14 at 23:25
  • 10
    there **are workarounds :)** depending on the restrictions/limitations you can **import** an external data without using an external location or even script element... one of the methods is embedding your script as binary data inside an image, without CORS limitation (allowing every domain), then fetching it into a canvas element, *(which **won't get tinted**) * reverse calculated the text from the image and embedding an inline-script with its content, alternatively encode the fetched text to base64 (which is domainless) and create a script with `src` attribute ""fetching"" that resource. ;) –  Nov 27 '15 at 23:31
  • @vagaroso [☕](http://icompile.eladkarako.com/wp-content/uploads/2015/12/oh_you_too.gif) –  Dec 19 '15 at 07:03
  • 1
    sadly, the method mentioned doesn't seem to work even on sites like github.com, where trying to even reference an image on an external site throws a CORS exception – Michael Dec 15 '17 at 23:57