View Sidebar
Defeating Chrome’s Content-Security-Policy Header via a Chrome Extension

Defeating Chrome’s Content-Security-Policy Header via a Chrome Extension

December 17, 2012 2:35 pm1 comment

This one was fun. While working on Feedhound, we suddenly started getting this error:

Refused to connect to 'https://feedhound.co/' because it violates the following Content Security Policy directive: "connect-src https://*.facebook.com http://*.facebook.com https://*.fbcdn.net http://*.fbcdn.net *.facebook.net *.spotilocal.com:* https://*.akamaihd.net ws://*.facebook.com:* http://*.akamaihd.net".

We were wondering what this message was. It turns out, apparently, that Facebook just started implementing the new HTML5 Content Security Policy standard in Chrome and Safari. While designed to prevent cross-site-scripting (XSS) attacks and enhance security, the new CSP policy is a huge problem for Chrome extensions, which often rely on the ability to create and call external scripts in order for the extension to, ahem, work properly. Since this is a new protocol, it isn’t turned on in Firefox yet, but it soon will be.

So we freaked out for a bit, and then remembered that Chrome has the chrome.webRequest API that lets you intercept headers and rewrite them. A couple hacks later, and voila:

chrome.webRequest.onHeadersReceived.addListener(function (details)
{
	for (i = 0; i < details.responseHeaders.length; i++) {
		if (details.responseHeaders[i].name.toUpperCase() == "X-WEBKIT-CSP") {
			details.responseHeaders[i].value = "default-src *;script-src https://*.feedhound.co https://*.facebook.com http://*.facebook.com https://*.fbcdn.net http://*.fbcdn.net *.facebook.net *.google-analytics.com *.virtualearth.net *.google.com 127.0.0.1:* *.spotilocal.com:* chrome-extension://lifbcibllhkdhoafpjfnlhfpfgnpldfl 'unsafe-inline' 'unsafe-eval' https://*.akamaihd.net http://*.akamaihd.net;style-src * 'unsafe-inline';connect-src https://*.facebook.com http://*.facebook.com https://*.fbcdn.net http://*.fbcdn.net *.facebook.net *.spotilocal.com:* https://*.akamaihd.net ws://*.facebook.com:* http://*.akamaihd.net https://*.feedhound.co";
		}
	}
	return {
		responseHeaders : details.responseHeaders
	};
}, {
	urls : ["*://*.facebook.com/*"],
	types : ["main_frame", "sub_frame", "stylesheet", "script", "image", "object", "xmlhttprequest", "other"]
},
	["blocking", "responseHeaders"]
);

Problem solved! The above listener needs to be added to the local extension resources and run as a background script. Also, the above is to modify the Facebook CSP to include our scripts at feedhound.co only for people who have installed our extension, and we have made sure to not overrite Facebook's carefully considered CSP in order to avoid leaving our users vulnerable to the same sort of XSS attacks that the CSP is designed to prevent.

In other news, we are super close to launching and I'm excited for that to happen!

1 Comment

  • Thank you very much, I was looking for a solution for this problem the better part of the day.