Secure Chrome extensions: Content Security Policy
eval are all effective mechanisms for mitigating cross-site scripting attacks. Implementing and enforcing such policies is simply a good idea.
Recognizing these advantages, Chrome’s engineers have extended CSP’s reach beyond websites into other areas of the browser where policies can serve as a defense against attacks. Most notably, policies can be applied to packaged applications and extensions. Both can make use of Chrome’s powerful and modular set of extension APIs, which give developers capabilities above and beyond what it makes sense for the web platform to offer normal websites. To whatever extent possible, therefore, developers need to ensure that those additional capabilities aren’t leaked out to the broader web. Content Security Policies mitigate this risk by helping developers ensure that the only code that runs with elevated privileges is their own.
Defining policies for an extension is quite straightforward, and we’re working to add them to all the sample extensions in the Chromium project. Walking through one of these samples together should give you a good idea of how it all works.
https://maps.googleapis.com to geolocate an address, and finally displays a static map image from
https://maps.google.com.1 A sufficiently paranoid policy would use a
default-src policy directive to deny access to everything by default, and then specifically whitelist only those resources via
img-src directives. I’ve annotated Mappy’s definition (which does exactly that) below:
# Block everything, then whitelist from there.
# Accept CSS from the extension's package.
# Allow XHR connections over HTTPS to Google Maps APIs.
# Allow images from Google Maps to load over HTTPS.
For normal websites, content security policies are delivered via an HTTP header. Chrome extensions use the same policy syntax, but define policies in the package’s manifest JSON as a simple key-value pair. Simply take the policy you’ve defined, and add it to
manifest.json: you can see how Mappy’s CSP is defined by visiting Chromium’s source repository.
<script> block into a
background.js file. For Mappy, the
background.html change is captured in this diff, and the
popup.html change is visible in this diff.
That’s it! Once you’ve defined a policy, and adjusted your extension’s code to match it, just test the extension locally, bump the version number, and push the update to your users. They’ll be more secure, and the world will be a (slightly) better place.
Your task is clear: update the extensions you own! It’s very straightforward work, and a real win for security. Content Security Policy support was added to Mappy in revision 106043; take a look at the code review to get some implementation ideas for your own extensions.
At the same time you’re working on your extensions, the Chromium team is working to set a better example by updating the 70 or so sample extensions and applications that Chromium makes available to include the new
content_security_policy manifest entry. It’s easy work – following the steps listed above takes less than half-hour on average – but 70 is a big number, so we’re a bit behind. You can follow our progress on that effort at crbug.com/92644: star the bug if you’re interested in updates, and pitch in if you’re interested! Patches are welcome: just send any code reviews my way (
Whenever possible, load resources over HTTPS rather than unencrypted HTTP. This has a number of benefits for privacy and security, most importantly (for our current context) a guarantee that the code you’re loading hasn’t been modified since it left the server. Active network attackers need to do a lot more work to inject code into a HTTPS stream, wheres it’s a trivial task via HTTP. ↩