Using Content-Security-Policy with multiple policies

5 years ago

Stuart Larsen #article


Did you know it's possible to use multiple content-security-policies on the same resource? This article will cover some of the in's and out's of using multiple policies.

If you're new to Content-Security-Policy I'd highly recommend checking out this article first: An Introduction to Content Security Policy.

tl;dr; all policies are enforced equally, any of the polices can block the overall resource/request

Policy delivery

Content-Security policy can be applied in two different ways: http header and <meta> tags.

The header is the most common and recommended. Applying CSP is as simple as setting 'Content-Security-Policy' or 'Content-Security-Policy-Report-Only' on the HTTP response.

The <meta> can be used as an http-equivalence to set the header. For example

<meta http-equiv="Content-Security-Policy" content="default-src https://cdn.example.net; child-src 'none'; object-src 'none'">

It's highly recommended to use the HTTP header over the meta tag. This is because:

  • <meta> Content-Security-Policy isn't applied until the meta tag is seen, so any content above the meta tag is not protected by CSP (such as <title> or other scripts/styles)
  • A number of very important directives aren't supported in the meta tag, including report-uri, frame-ancestors, and sandbox

Sending Multiple Policies

There's two way to have multiple policies.

  • The server sends (either through header/meta tag) multiple content-security-policies (multiple 'Content-Security-Policy' or 'Content-Security-Policy-Report-Only' or both)
  • The policy uses comma separated list of policies. Not as common, but you can specify multiple policies on the same line by using the comma operator. For example; Content-Security-Policy: default-src 'self', default-src 'https:'

Effect of Multiple Policies

When a web server delivers multiple policies, they are both enforced. This means that the either policy can block a resource from being loaded.

default-src 'self', default-src https:;

In this comma-separated example, a resource in question will only pass through if it's both from 'self' and over 'https:'. Had the two policies been merged into a single policy (default-src 'self' 'https:'), it would have been allowed if it was from either 'self' OR 'https:'.

Why use multiple policies?

There might be more uses, but the two I've seen are for 'upgrade-insecure-requests' and testing out a new policy.

upgrade-insecure-requests

upgrade-insecure-request doesn't report when it upgrades a resource, so the spec https://w3c.github.io/webappsec-upgrade-insecure-requests/#reporting-upgrades recommends setting multiple policies to both upgrade, and report.

upgrade-insecure-requests;
default-src https:;

Content-Security-Policy-Report-Only

default-src https:;
report-uri https://abc.endpoint.csper.io/;

Testing out a new policy

You have a policy already applied in enforce mode, and you want to test a new policy in report-only mode to see how it works.

Reporting with Multiple Policies

I set up a couple of demo's that can be found at https://github.com/csper-io/csper-demos to check out a couple of questions I had.

Some facts (tested with Chrome):

  • Each policy is evaluated and reported on (it doesn't short circuit)
  • In the "original-policy" only the violated directive is placed, not both.
  • And again, even iff you use comma separated policies, only the individual policy is included in the report

All very sensible.

Resources

Conclusion

If you have any questions or comments, please reach out! I'd love to chat stuart@csper.io.

Subscribe for updates?

Stay up to date with the latest Content Security Policy news, product updates, discounts, and more!