[This article was first published on The Jumping Rivers Blog, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)


Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Heads up! We’re about to launch WASP, a Web Application SecurityPlatform. The aim of WASP is to help you manage (well, you guessed it)the security of your Posit Connect application using Content SecurityPolicy and Network Error Logging. More details soon, but if thisinterests you, please get intouch.


This blog post is aimed at those who are somewhat tech literate butnot necessarily a security expert. We’re aiming to introduce the conceptof Content Security Policy and teach some of the technical aspects.


In 2018, a hacking group calledMagecart exploited avulnerability on the British Airways website that allowed them to injectJavaScript. The JavaScript code was used to send customer data to amalicious server, succeeding in skimming the credit cards of 380,000transactions before the breach was discovered. This type of attack comesunder the umbrella of cross-site scripting (XSS) – where malicious code(often client-side JavaScript) is injected into the browser.

What is Content Security Policy?Content Security Policy (CSP) isa framework of modern (ish) browsers, that allows a developer to protectan application through the use of the Content-Security-Policy HTTPheader. It’s used to give applications an extra layer of security –safeguarding against attacks such as cross-site scripting. In this blogwe’re going to take you through some of the basics of Content SecurityPolicy and show you why it’s a necessity for modern applications.

How will Content Security Policy help me?In one way or another, you have made it to this blog post onjumpingrivers.com. This means yourbrowser has already loaded a tonne of assets that this page needs tolook and act in the way it does (JavaScript, fonts, stylesheets).Without CSP, the browser will trust and not question any loadedresources from any source. If there are any vulnerabilities with thispage, an attacker could run client-side JavaScript to import contenthosted from their own source; for instance, a fake form or a maliciousclick event to skim user details or steal data from a database, justlike with British Airways. Your browser simply says “Yes, why wouldn’t Itrust this code?”. This is where CSP comes into play.

How does CSP link to R?Have you ever used the {shiny}, {quarto} or {rmarkdown} R packages tomake web applications or documents? If you then took the extra step todeploy your app, you should be asking the question “How safe is it todeploy this?”. {shiny}, {quarto} and {rmarkdown} pull in a lot ofexternal resources; css, JavaScript etc. This leaves them vulnerable tocross-site scripting attacks, just like British Airways. Using CSP, wecan protect our {shiny} / {rmarkdown} documents against these attacks.

The technical basicsA Content Security Policy HTTP header is set on the server side, butprotects the client side. A CSP header is split into directives – eachdirective enabling you to specify an allow list (in some cases, a denylist) of valid sources for content that the browser can (or is notallowed to) load. For instance, one of the more common directives,script-src, allows us to specify valid sources for scripts. Anyscripts that are from a source not listed within this directive will beblocked from executing in the browser. A basic CSP header usingscript-src might be

Content-Security-Policy: script-src 'self'` The metasource, self, is telling the browser to allow scripts to beloaded from our domain. As there are no others sourced listed with it,we are telling the browser to only allow scripts to be loaded fromour domain. There are other metasources:

  • 'self': Content from the same domain,
  • 'none': Nobody can include this functionality. In the case above,this would mean we accept scripts from no sources.
  • A nonce / hash:Accept code with a specific nonce / hash.

Of course, we can also specify specific URL / domains. For instance,

Content-Security-Policy: script-src 'self' https://posit.co/ would allow loading of scripts from our own domain, and Posit. Othercommon directives include

  • default-src: Default values for *-src directives.
  • font-src: Valid sources for fonts loaded using the @font-faceCSS at-rule.
  • frame-src: Valid sources for embedded frame contents.
  • img-src: Valid origins from which images can be loaded.
  • navigate-to: Restricted URLs from which a document can initiatenavigation.
  • style-src: Valid sources for stylesheets.
  • media-src: Valid sources for loading media using , and elements.

For a full list, see the MDN WebDoc.

Reporting Content-Security-Policy violationsIf an attacker had found any vulnerabilities on our site, then using thedirectives above we would be blocking a good bunch of potential attacksfor users on modern browsers. However, users on browsers (mainlyInternet Explorer) that still do not support the CSP directives you’vechosen are still at threat. It’s important that we understand which CSPdirectives are being targeted on our site, to protect the vulnerable onold browsers.

Directives are split into two categories; blockers and reporters.Blockers block input into the application (think script-src) andreporters deliver reports about the blocks. This allows us to understandwhich of our CSP directives are being targeted.

The most important reporting directive is report-to. However, it’spredecessor, report-uri, still plays a crucial role. In fact, allbrowsers will fall back to report-uri if it can’t find report-to.We’ll go into more detail on the differences between the two in a laterblog, but for now we’ll look into report-uri (it’s a tad simpler).

The report-uri directive allows us specify the URL(s) to which our CSPviolation should be reported. These URLs are usually API endpoints,which process the report JSON. The following HTTP header would POST anyviolations to the csp-reporting endpoint on our domain

Content-Security-Policy: script-src 'self'; report-uri /csp-reporting Any reports sent to this endpoint will beContent-Type: application/reports+json and contain four importantpieces of information (plus some others):

  1. blocked-uri: URI of the blocked resource
  2. document-uri: URI of the document in which the violation occurred
  3. original-policy: The original Content Security Policy
  4. violated-directive: The CSP directive that was violated

The format will look something like

{ "csp-report": { "document-uri": "https://magecart.com/example.html", "referrer": "", "blocked-uri": "https://badwebsite.com/css/style.css", "violated-directive": "script-src 'self'", "original-policy": script-src 'self'; report-uri /csp-reporting", "disposition": "report" }} This report indicates that on the page magecart.com/example.html,something has tried to load the style file located atbadwebsite.com/css/style.css. However, because we have thescript-src directive set to "self", only scripts from our own domainmay be sourced.

Some limitationsWhilst CSP is a great addition to the security toolbox, there are some“limitations”:

  1. It’s not a magic wand. It’s a control to cut down on yourapplication’s exposure – it will not patch vulnerabilities. Think ofit like a firewall – it’s a secondary control, a defence technique.Mostly in case the developers have missed something. If you’rehaving trouble with any security issues, feel free to get intouch with us for advice.
  2. It’s only useful for client-side attacks on your application. Itdoes not help with server-side, database attacks or anything inbetween.
  3. OK, this last one isn’t really a limitation, more of a warning. It’snot on by default. The Content-Security-Policy HTTP header has tobe added manually with each policy individually specified.

If Content Security Policy or Shiny app security in general interestsyou or you want more news on WASP, our new Web Application SecurityPlatform, then please email info@jumpingrivers.com and we can discusshow to set this up for your applications.

For updates and revisions to this article, see the original post

To leave a comment for the author, please follow the link and comment on their blog: The Jumping Rivers Blog.


R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.


Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.Continue reading: Content Security Policy – Why You Need It