Question

I just completed Javascript course from Codecademy. I tried to make a chrome extension that will show this page. So I looked at how to make a sample chrome extension and created the extension(basically copy pasted the entire site code). I am getting this error

Refused to load the script 'http://dota2.cyborgmatt.com/prizetracker/data/ti4.json?
callback=jQuery11020032285090535879135_1399794129146' because it violates the
following Content Security Policy directive: "script-src 'self' 
chrome-extension-resource:"

I tried looking about Content Security Policy and added this line

"content_security_policy": "script-src 'self' http://dota2.cyborgmatt.com/; 
object-src 'self'"

I don't have complete idea of what I am doing but I tried reading up various stuff but failed to understand. Somebody help. Thanks in advance.

Était-ce utile?

La solution

It's not a good idea to just grab a copy of the page's code that does this.

Consider: you get a Content Security Policy error, because you're trying to execute a piece of code from a remote server. While you can relax the policy, let me first explain why is this a security problem.


Currently, your code loads http://dota2.cyborgmatt.com/prizetracker/data/ti4.json and executes its contents, without verifying what they are. Right now it looks like this:

populatePrizePool({"dollars":3129676});

But: this is a website you do not control.

Imagine: you write your extension, it becomes popular, admins of the site notice the unusual traffic, change their code to load http://dota2.cyborgmatt.com/prizetracker/data/ti4_.json instead, and after a bit of googling replace the original link's contents with this:

alert("By the way, Ramana Venkata is stealing our data. Sincerely, cyborgmatt.com");

And suddenly, your extension doesn't work, you have an angry mob of users, and are slightly embarrassed.

You see the problem? It could be worse, as the replacement code can be as evil as JS permits. Since HTTP traffic is trivial to intercept, it doesn't even take cyborgmatt.com admins to inject arbitrary code in your extension, and that is why it's not even possible to relax the policy in this way.


Now, to solve the problem. Instead of AJAX-loading the code, you should just load this file, parse it to get the JSON data (i.e. {"dollars":3129676}), safely parse and validate that data, and only then use it. This way, if the above scenario happens, at least nothing evil comes of it.

Step 1: Get the data.

Replace the $.ajax call with XHR:

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
  if (xhr.readyState == 4) {
    parseAndValidate(xhr.responseText);
  }
};
xhr.open("GET", "http://dota2.cyborgmatt.com/prizetracker/data/ti4.json", true);
xhr.send();

Step 2: Parse and validate.

You have a string that you expect to have the following format: populatePrizePool(SOME_JSON);, and you expect the JSON data to contain a non-negative number dollars.

function parseAndValidate(str){
  var some_json;

  // First, extract `SOME_JSON` with a regular expression:
  if(str.match(/populatePrizePool\((.*)\);/)) {
    some_json = str.match(/populatePrizePool\((.*)\);/)[1];
  } else {
    throw Error("Unexpected format for ti4.json");
  }

  // Second, _safely_ parse `some_json`:
  var data = JSON.parse(some_json); // Will throw an exception if something's not right

  // Third, ensure that the JSON has the required data:
  if( !data.dollars || typeof data.dollars !== "number" || data.dollars < 0) {
    throw Error("Unexpected data format for ti4.json");
  }

  // Finally, call the function:
  populatePrizePool(data);
}

This may be a little overkill for your tiny project, but it's a learning experience. Do not blindly trust data you don't control, even less code you don't control.

Autres conseils

This is only possible with HTTPS resources, not HTTP resources, according to the docs:

If you have a need for some external JavaScript or object resources, you can relax the policy to a limited extent by whitelisting secure origins from which scripts should be accepted. We want to ensure that executable resources loaded with an extension's elevated permissions are exactly the resources you expect, and haven't been replaced by an active network attacker. As man-in-the-middle attacks are both trivial and undetectable over HTTP, those origins will not be accepted. Currently, we allow whitelisting origins with the following schemes: HTTPS, chrome-extension, and chrome-extension-resource.

Thus, origins that begin with http: are categorically disqualified from inclusion in an extension's script-src CSP directive.

Luckily for you, the resource in question has an HTTPS variant. In your extension's code, change the line:

var baseURL = ( location.protocol == 'https:' ) ? 'https://dota2.cyborgmatt.com/' : 'http://dota2.cyborgmatt.com/';

to one that uses HTTPS unconditionally:

var baseURL = 'https://dota2.cyborgmatt.com/';
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top