3

I am building one chrome extension which uses a JavaScript library customized to a specific web domain. It is a restriction of that library to be called only from that specific domain (license issues actually).

I want to load that js library into my chrome extension, but the extension gives a Content Security Policy error as the library to be used comes from a HTTP (not HTTPS) URL. I searched StackOverflow for this and the only options I see are either to load that file locally or through message passing.

Can someone please tell what code should I have in my background.js and content.js and what permission to add in my manifest.json?

The website to get that js library is, e.g., http://library.com/js/xy.js. I know there should be something else like some piece of code in content.js. How can I load the code from that domain?

manifest.json:

{
    "manifest_version": 2,
    "name": "abc",
    "version": "0.2",
    "description": "abc",
    "content_security_policy": "script-src 'self'; object-src 'self'",
    "browser_action": {
        "default_icon": "MM_logo_2009.png",
        "default_popup": "tab/popup.html"
    },
    "background": {
        "scripts": ["event.js"],
        "persistent": false
    },
    "permissions": [
        "http://library.com/js/xy.js",
        "bookmarks",
        "tabs",
        "storage",
        "http://*/*", 
        "https://*/*"
    ]
}

event.js:

var xhr = new XMLHttpRequest();
xhr.open("GET", "http://library.com/js/xy.js", true);
xhr.onreadystatechange = function() {
    if (xhr.readyState == 4) {
        // innerText does not let the attacker inject HTML elements.
        document.getElementById("resp").innerText = xhr.responseText;
    }
}
xhr.send();
Xan
  • 74,770
  • 16
  • 179
  • 206
  • Wait, you need it in a content script, or the event script itself? You'll need to explain better. – Xan Dec 11 '15 at 11:05
  • i just need the library to be injected to my extension this event.js is my background page and this code is written in it @Xan – Ammad Akhtar Dec 11 '15 at 12:55
  • "Injected to my extension" is ambiguous since you're also using a content script. Where exactly do you want it injected - the background? The content script context? The page context? – Xan Dec 11 '15 at 12:56
  • @Xan in the content script but there should be a proper way to communicate it e.g background page should call something like chrome.tabs.executeScript(null, { file: 'content.js' }); – Ammad Akhtar Dec 11 '15 at 13:01
  • Well, then that's _much_ easier than what you describe! Just save your `responseText` and call that with `code` parameter instead of `file`. – Xan Dec 11 '15 at 13:07
  • save my responseText? @Xan – Ammad Akhtar Dec 11 '15 at 13:27
  • see also http://stackoverflow.com/q/9515704/32453 – rogerdpack Oct 18 '16 at 17:33

1 Answers1

5

A very direct, and stupidly dangerous way:

If this is really the only way you can do this (loading code over HTTP), then you have to resort to allowing eval:

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

and then

var xhr = new XMLHttpRequest();
xhr.open("GET", "http://library.com/js/xy.js", true);
xhr.onreadystatechange = function() {
    if (xhr.readyState == 4) {
        eval(xhr.responseText);
    }
}
xhr.send();

This should be the very last resort as it opens your highly privileged environment to arbitrary code execution from anyone who can MITM your connection.

Since it's HTTP, there is no guarantee whatsoever of the identity of the sender or the integrity of the script.

Don't be surprised if this code gets rejected by Chrome Web Store!

Fortunately, there is a way to at least partially mitigate the risk.

Use protection.. err, sandboxing:

There's even a whole guide on it in the docs, "Using eval in Chrome Extensions. Safely."

You then do the same, but in a sandboxed page (e.g., an <iframe> in your event/background page), and communicate with it using postMessage. This way, you can validate the communication and not provide any direct access to extension API for the code being evaluated.

Xan
  • 74,770
  • 16
  • 179
  • 206
  • i added the con ten script policy u said but i didn't get the library from that page..am i missing any call to xml http req? like i am direct just using that req like posted in my question – Ammad Akhtar Dec 11 '15 at 11:25
  • Let me put it this way: this is a really dangerous piece of code. If you do not understand it fully, _you should not be doing this_. – Xan Dec 11 '15 at 11:27
  • but this is like last option for me of calling the library... the sandbox method i couldn't understand if u know how to implement it kindly could u write a piece of code here? @Xan – Ammad Akhtar Dec 11 '15 at 11:28
  • 1
    Sorry, no. You should rethink your approach if you can't adapt this solution. Also, Stack Overflow is not a coding service: we're not here to do your job for you. – Xan Dec 11 '15 at 11:31
  • the code i used is not dangerous in a sense that the website where it is hosted is mine so there is not threat MITM .....even i used suggestion u gave it still didn't work @Xan – Ammad Akhtar Dec 11 '15 at 11:35
  • I don't see a need to load the js from the website. simply include it locally. – Zig Mandel Dec 11 '15 at 12:28
  • look to make it simple this library is customised one after i bought license for it and it has to run from my website as it is particularly tied to that domain....yes i can call it locally but couldn't find what to exact allow in manifest and where should i call it locally...@ZigMandel – Ammad Akhtar Dec 11 '15 at 12:57