Cordova/PhoneGap & CSP (QuickTip)

I just wanted to share a few tips regarding the Content Security Policy meta tag that we need to use in PhoneGap/Cordova apps. I’m not going to cover all the gory details — for that, there are plenty of great sites.

I’m just going to focus on a few specific use cases when it comes to the intersection of CSP and Cordova/PhoneGap, but there’s a couple things we need to mention first.

The CSP Meta Tag

CSP directives are specified by a meta tag, like so:

<meta http-equiv="Content-Security-Policy"
    contents="...">

CSP Directives

CSP controls what sources are permitted and what sources aren’t. Because there are many different types of assets our page might need, CSP also allows us to be very granular with respect to what types of assets can be loaded from which sources. There’s several directives available, like so:

Directive Description
img-src Image sources (like PNG, JPG, SVG, etc.)
media-src Video/audio sources
script-src Script sources
style-src Stylesheet sources
font-src Webfont sources
default-src Fallback for most directives

This isn’t the entire list of available directives, so you’ll want to check out the links at the head of this article for all the possibilities, but this should give you a pretty good idea of the granularity of CSP.

Furthermore, it’s important to note that there is a hierarchy of sorts — if you don’t specify img-src, but do specify default-src, then default-src is used instead. If you specify both, however, the values won’t inherit from default-src.

CSP Sources

A source is either a URL or a special keyword. A URL can look like this:

  • http://www.example.com — allow resources from this domain, including any pages on it
  • http://*.example.com — allow resources from this domain, including any subdomains.
  • *://*.example.com — allow resources from this domain, any subdomains, and any URL scheme
  • *://*.example.com:* — allow resources from this domain, any subdomains, any URL scheme, and any port.

NOTE: Although it might appear that you can use wildcards anywhere, you can’t. You can only use a wildcard for the URL scheme, the left part of the domain, and the port.

There are four keywords that you can also use:

  • 'none' — indicates that no source is permitted. This disables access for the specified directive.
  • 'self' — indicates that local resources are permitted.
  • 'unsafe-inline' — permits inline scripts/styles
  • 'unsave-eval' — permits eval() and its ilk.

CSP Syntax

Each directive can have any number of sources. Each one is separated by a space. The entire set of directives are separated by semicolons. This makes things a little difficult to read, but that’s the way it’s built. For example, here’s a sample CSP tag:

<meta http-equiv="Content-Security-Policy" 
 content="default-src 'self' https://*.example.com;
              img-src 'self' https://images.example.com data:;
           script-src 'self' https://scripts.example.com">

This isn’t a terribly useful CSP, but it does illustrate the syntax.

Common Cordova Uses

With all that out of the way, here’s some common tasks you might need to perform in a Cordova app — along with the directives you need to specify to permit them:

Task Directive Value
iOS Support default-src gap://* (1)
Allow web socket communication default-src ws://* (2)
Execute / load local resources default-src 'self' (3)
Load data: images img-src data:
Permit eval() script-src 'unsafe-eval' (4)
Permit inline scripting script-src 'unsafe-inline' (5)
Permit inline styles style-src 'unsafe-inline'

Notes:

  1. This is critically important for your Cordova/PhoneGap apps running on iOS. Without it, plugins and Cordova events won’t work.
  2. If you use web sockets for communication, you’ll need to allow this URL scheme. Our example allows communication with any host on any port, but ideally you’ll be more specific.
  3. You should always have 'self' in any directive so that you can load local resources. If you override any other directive, you’ll need to specify 'self' there too.
  4. Only allow eval() if you absolutely must do so. Some plugins, libraries and frameworks will require it, but if you can avoid it, this should be avoided, as it can be a huge security hole.
  5. Only allow inline scripting if you absolutely must. Again, some frameworks and such might require it, but it’s a huge security risk if you’re injecting dynamic HTML using untrusted data.

What about BrowserSync?

I really, really, really like to use BrowserSync when rapidly iterating, especially because it lets me have the same content loaded across multiple devices, including the desktop. When I make changes, the content can automatically be updated.

In order to use BrowserSync, however, you need to enable certain CSP rules. These should only be enabled during development, unless you’re using another framework or plugin that requires them:

  • Add ws://* to the default-src directive — BrowserSync communicates over web sockets.
  • Add 'unsafe-inline' to the script-src directive.

You can also use phonegap serve and the PhoneGap Developer app for a similar experience. However, I’ve only had limited luck in getting this to work well within my typical build setup (which has all sorts of stuff going on!), while BrowserSync works a peach.

Leave a Reply