How we updated our Content Security Policy using our own product
Tags: monitoring, security
Published: 2021-05-27 19:12:12

By: [Mark Story](https://blog.sentry.io/authors/mark-story)

Everyone talks about creating content. But what about controlling it? In this Dogfooding Chronicle, I’ll walk you through how we updated our Content Security Policy using [Discover](https://docs.sentry.io/product/discover-queries/) — and how we’re keeping watch with [Dashboards](https://sentry.io/features/dashboards/).

#Defining Content Security Policies#

As the Internet evolves, so must our security mechanisms. It’s why same-origin policies (a Netscape-era directive in which resources from one origin are unable to modify or read data from another origin) put your application at risk for clickjacking and cross-site scripting attacks. That’s because same-origin policies have a weakness that enables third-party entities to have the same access rights as trusted entities. Content Security Policies (CSPs) address this blind spot by approving specific content types — everything from [JavaScript](http://sentry.io/for/javascript) sources to CSS fonts, HTML frames and embeddable Java applets.

Put simply, a CSP lets a browser know which content sources are to be trusted — and which aren’t. And when there is a CSP violation, browsers can submit the error to a `report-uri`. What’s more, if you have Sentry, these violation reports are integrated into your application’s monitoring dashboards.

During our most recent penetration test, we found that some of the CDN domains in our allow list were hosting potentially dangerous scripts. One of our recommendations from this audit was to refine and improve our CSP rules.

#Discover-ing ‘report-only’ mode#

Content Security Policies have two modes. The first mode enforces and actively blocks resource loading and execution, while the second collects the errors that would happen if the rules were active. This mode is set via the invaluable `Content-Security-Policy-Report-Only` header that defines your CSP rules.

When I combined this ‘report-only’ feature with [Discover queries](http://sentry.io/features/custom-queries), I was able to visualize all the errors coming from `report-only` mode. Now I could view the impact of fixes in real time, and see which rules were being broken — without disrupting customers.

#Sussing out Safari#

While `report-only` mode worked well, I did encounter some hiccups in Safari, as it’s been known to jumble its report-only and enforced modes. This meant I was getting errors for sources that should be allowed. To verify that these errors were caused by Safari bugs, I used our staging environment to test Safari with only the new rules being enforced. And using [Dashboards](https://docs.sentry.io/product/dashboards/custom-dashboards/), I was able to fully view Safari’s impact on our CSP errors.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/914f390k14wdrmfjldh3.png)

#A glance at the solution#

Like reading a good detective novel, once I solved this problem, another, more confounding problem bubbled up to take its place. Our Jira integration was having trouble integrating with our CSP. Because our [Jira integration](http://sentry.io/integrations/jira) includes an embedded ‘glance view’, I could view Sentry data alongside other fields like assignee, priority and labels. After reviewing these embedded views, I discovered the issue: outdated libraries that relied on `eval()` expressions which are not allowed in our CSP rules.

While upgrading these libraries to newer versions resolved a large number of errors, it didn’t solve them all. And though I was unable to reproduce these last few errors, I was able to use Discover’s tag breakdowns to narrow things back down to — you guessed it — a Safari-specific issue:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xcvfvbbvv41rvqcdhwje.png)

#CSP 3: Coming to a browser near you#

The newest iteration of CSP has been in production for years, and is about to be fully released. Which is why we have defined rules for all three levels to get the broadest — and sturdiest — coverage possible. Doing so has both simplified our CSP configuration and improved our resilience to cross-site scripting. Which brings me to my last tip: it’s important to define directives in the order of their levels. Browsers will often stop parsing a directive when they find something they don’t know, so it’s important that there are specific directives for all three CSP levels.

Developing a Content Security Policy isn’t about being fussy — it’s about being functional. Data and code from untrusted sources should not have the same privileges as the trusted programmer’s code. By implementing a well-defined CSP, you can mitigate attacks, control assets, and breathe easier.