Content Security Policy: Frame Ancestors

Background

I’ve been working on introducing a Content Security Policy (CSP) for some time and today is the day where a first, minimal version of our policy will start to be enforced.

So, what’s a Content Security Policy? Mozilla explains it like this:

Content Security Policy (CSP) is a feature that helps to prevent or minimize the risk of certain types of security threats. It consists of a series of instructions from a website to a browser, which instruct the browser to place restrictions on the things that the code comprising the site is allowed to do.

Today, specifically, we’ll start rolling out a minimal policy that only contains a frame-ancestors directive.

What Changes?

Example, policy as applied for https://www.tocco.ch:

$ wget -q -S --spider https://www.tocco.ch
  HTTP/1.1 200 
  ...
  content-security-policy: frame-ancestors https://home-office-stellen.ch https://software-job.ch https://zuercher-jobs.ch; report-uri https://reports.tocco.ch/csp?app=nice&ns=tocco; report-to csp-reports
  ...

frame-ancestors restricts who can embed (e.g. <iframe>) a webpage. Restricting embedding is important to prevent clickjacking.

As can be seen in above example, sites that embed our application, https://www.tocco.ch, will have to be listed explicitly. This is configured in Ansible’s config.yml:

tocco:
  # ...
  installations:
    tocco:
      allowed_frame_ancestors:
      - https://home-office-stellen.ch
      - https://it-jobs-switzerland.ch
      - https://software-job.ch
      - https://zuercher-jobs.ch
      # ...

Note that our backend, /tocco, uses a different policy forbidding embedding unconditionally:

$ wget -q -S --spider https://www.tocco.ch/tocco
  HTTP/1.1 200 
  ...
  content-security-policy: frame-ancestors 'none';report-uri https://reports.tocco.ch/csp?app=nice&ns=tocco;report-to csp-reports;
  ...

I don’t belive there is ever any reason to embed our client.

When to allow Embedding?

Only pages you trust should be allowed to embed your page.

What Happens when Embedding isn’t Allowed?

The browser will show an error instead of the embedded page:

iframing not allowed

In the example above, an <iframe> is used to embed https://www.tocco.ch/Unternehmen/Stellen but the page that contains the <iframe> is not listed in the CSP’s frame-ancestors.

How will This be Rolled Out?

WordPress

Embedding has never been allowed on our WordPress pages.

There is currently no defined way to allow embedding. We’ll add a mechanism for this, should be be presented with a valid use case.

Tocco

Rollout will happen in steps:

  1. Rollout to our own installations (mostly done)
  2. Rollout to selected, low-risk customers. Namely, those already using WordPress. Those customers don’t use our CMS and there isn’t much they could want embed. (will happen shortly)
  3. Everyone else. (in ~2 months)

How is Ensured Embedding Pages do not Break?

We’ve added a report-only policy some time ago:

$ wget -q -S --spider https://smc.tocco.ch
...
content-security-policy-report-only: frame-ancestors 'none'; report-uri https://reports.tocco.ch/csp?app=nice&ns=smc; report-to csp-reports
...

Note the report-only in the HTTP header name. This policy will send reports to https://reports.tocco.ch about policy violations but the policy is not enforced, and embedding will still work. We’ll wait some longer until we have had this enabled for three months on all pages. Then we’ll configure all installations according to the observed violations.

It’s possible that the initial policy will miss some pages that had not been opened for three month but that seems like an acceptable risk.