New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement "Content Security Policy" (CSP) #1542

Closed
robocoder opened this Issue Aug 1, 2010 · 18 comments

Comments

Projects
None yet
6 participants
@robocoder
Contributor

robocoder commented Aug 1, 2010

Reference:

The proposal would be to add the CSP header, "X-Content-Security-Policy:" with a policy-uri pointing to a static file (which can be cached by the user agent).

Because the specification says the UA must compute the intersection for multiple CSP headers, if a system administrator imposes a more restrictive policy (e.g., via Apache's "append header" directive), it doesn't matter if this feature is enabled by default or not -- a supporting UA will use the more restrictive policy.

Whether or not we implement this feature, CSP, however, will increase the support burden if users complain about why JavaScript may be failing (e.g., not tracking). That is, we have to see the server's response header to diagnose the cause.

@robocoder

This comment has been minimized.

Show comment
Hide comment
@robocoder

robocoder Oct 25, 2010

Contributor

This is a wontfix. The base restrictions are:

  • no inline scripts
  • no code created from strings
  • no data: URIs
  • XBL bindings must come from chrome: or resource: URIs
Contributor

robocoder commented Oct 25, 2010

This is a wontfix. The base restrictions are:

  • no inline scripts
  • no code created from strings
  • no data: URIs
  • XBL bindings must come from chrome: or resource: URIs

@robocoder robocoder added this to the Future releases milestone Jul 8, 2014

@mattab

This comment has been minimized.

Show comment
Hide comment
@mattab

mattab Jan 16, 2015

Member

Maybe we can re-consider, maybe there would be a technical solution to have Piwik run in this CSP scenario?

Member

mattab commented Jan 16, 2015

Maybe we can re-consider, maybe there would be a technical solution to have Piwik run in this CSP scenario?

@mattab mattab reopened this Jan 16, 2015

@sebastianbergmann

This comment has been minimized.

Show comment
Hide comment
@sebastianbergmann

sebastianbergmann Jan 19, 2015

I am not an expert (neither on JavaScript in general nor on CSP in particular) but from what I understand Piwik's JavaScript tracker must not use inline JavaScript and eval().

sebastianbergmann commented Jan 19, 2015

I am not an expert (neither on JavaScript in general nor on CSP in particular) but from what I understand Piwik's JavaScript tracker must not use inline JavaScript and eval().

@fhemberger

This comment has been minimized.

Show comment
Hide comment
@fhemberger

fhemberger Jan 27, 2015

Contributor

@mattab It would be nice if Piwik included CSP in the admin backend for increased security (e.g prevent plugins from executing JS or loading resources from suspicious sources). CSP headers are only sent for documents, not for other page resources, so this won't interfere with calls to the tracking JS at all.

A brief overview on CSP can be found at http://content-security-policy.com

Contributor

fhemberger commented Jan 27, 2015

@mattab It would be nice if Piwik included CSP in the admin backend for increased security (e.g prevent plugins from executing JS or loading resources from suspicious sources). CSP headers are only sent for documents, not for other page resources, so this won't interfere with calls to the tracking JS at all.

A brief overview on CSP can be found at http://content-security-policy.com

@mattab mattab removed the wontfix label Apr 8, 2015

@mattab mattab modified the milestones: Mid term, Long term Apr 8, 2015

@mattab mattab added the c: Security label Apr 8, 2015

@mattab

This comment has been minimized.

Show comment
Hide comment
@mattab

mattab Apr 8, 2015

Member

it was also discussed in: Do not use eval function in JavaScript #5960 which requires Piwik.js tests: Replace JSLint with JSHint #7232

Member

mattab commented Apr 8, 2015

it was also discussed in: Do not use eval function in JavaScript #5960 which requires Piwik.js tests: Replace JSLint with JSHint #7232

@mattab mattab modified the milestones: Short term, Mid term Apr 8, 2015

@tsteur

This comment has been minimized.

Show comment
Hide comment
@tsteur

tsteur Apr 9, 2015

Member

To be clear, this issue is also about not using eval in piwik.js since #5960 was closed as a duplicate of this

Member

tsteur commented Apr 9, 2015

To be clear, this issue is also about not using eval in piwik.js since #5960 was closed as a duplicate of this

@mattab mattab added the Major label Aug 16, 2015

@mattab

This comment has been minimized.

Show comment
Hide comment
@mattab

mattab Oct 2, 2015

Member

@tsteur Having CSP in our LTS would really help especially some security strict Enterprise environment. Could you please do assessment what it would take not to use eval - is it possible, while still bundling the JSON encoder?

Member

mattab commented Oct 2, 2015

@tsteur Having CSP in our LTS would really help especially some security strict Enterprise environment. Could you please do assessment what it would take not to use eval - is it possible, while still bundling the JSON encoder?

@tsteur

This comment has been minimized.

Show comment
Hide comment
@tsteur

tsteur Oct 2, 2015

Member

we can replace it with JSON 3 https://bestiejs.github.io/json3/

I think there's only one other eval in Legacy piwik.js compatibility ftw and this one we can replace probably without much work.

Member

tsteur commented Oct 2, 2015

we can replace it with JSON 3 https://bestiejs.github.io/json3/

I think there's only one other eval in Legacy piwik.js compatibility ftw and this one we can replace probably without much work.

@tsteur tsteur self-assigned this Oct 2, 2015

@tsteur tsteur modified the milestones: 2.15.0, Short term Oct 2, 2015

@tsteur tsteur removed their assignment Oct 2, 2015

@mattab mattab modified the milestones: 2.15.0, Short term Oct 4, 2015

@mattab

This comment has been minimized.

Show comment
Hide comment
@mattab

mattab Oct 4, 2015

Member

Update: in #8896 we removed all uses of eval the piwik.js, by replacing JSON2 with JSON3. Latest piwik.js without eval is here: https://github.com/piwik/piwik/blob/master/js/piwik.js

We are one step closer to CSP support! 👍

What is our next step for fully supporting CSP?

Steps

  • Check whether piwik works with CSP enabled
  • Add FAQ to document that Piwik respects CSP
  • Add to list of features that CSP is supported
Member

mattab commented Oct 4, 2015

Update: in #8896 we removed all uses of eval the piwik.js, by replacing JSON2 with JSON3. Latest piwik.js without eval is here: https://github.com/piwik/piwik/blob/master/js/piwik.js

We are one step closer to CSP support! 👍

What is our next step for fully supporting CSP?

Steps

  • Check whether piwik works with CSP enabled
  • Add FAQ to document that Piwik respects CSP
  • Add to list of features that CSP is supported
@tsteur

This comment has been minimized.

Show comment
Hide comment
@tsteur

tsteur Oct 5, 2015

Member

I'm not sure which directives to set for CSP. @robocoder mentioned no inline scripts see #1542 (comment) This can be done but need to document how to do it in FAQ.

Which directives should one set to test it properly?

Member

tsteur commented Oct 5, 2015

I'm not sure which directives to set for CSP. @robocoder mentioned no inline scripts see #1542 (comment) This can be done but need to document how to do it in FAQ.

Which directives should one set to test it properly?

@fhemberger

This comment has been minimized.

Show comment
Hide comment
@fhemberger

fhemberger Oct 5, 2015

Contributor

Keep in mind, that IE 10-11 uses "X-Content-Security-Policy" and Safari < 7 uses "X-Webkit-CSP" in case you want to support those as well.

You should consider default-src, script-src, style-src, frame-ancestors; frame-src. See http://www.w3.org/TR/CSP/
Also a good idea would be to add 'upgrade-insecure-requests' for HTTPS environments, see: http://www.w3.org/TR/upgrade-insecure-requests/ and enable Strict-Transport-Security

To check if everything is working correctly, you can use 'report-uri', to log CSP violations (a good service is https://report-uri.io for setting this up).

Current browser support: http://caniuse.com/#feat=contentsecuritypolicy,contentsecuritypolicy2

Contributor

fhemberger commented Oct 5, 2015

Keep in mind, that IE 10-11 uses "X-Content-Security-Policy" and Safari < 7 uses "X-Webkit-CSP" in case you want to support those as well.

You should consider default-src, script-src, style-src, frame-ancestors; frame-src. See http://www.w3.org/TR/CSP/
Also a good idea would be to add 'upgrade-insecure-requests' for HTTPS environments, see: http://www.w3.org/TR/upgrade-insecure-requests/ and enable Strict-Transport-Security

To check if everything is working correctly, you can use 'report-uri', to log CSP violations (a good service is https://report-uri.io for setting this up).

Current browser support: http://caniuse.com/#feat=contentsecuritypolicy,contentsecuritypolicy2

@tsteur

This comment has been minimized.

Show comment
Hide comment
@tsteur

tsteur Oct 5, 2015

Member

Tested and worked for me. Took me a while to figure out why it didn't work in the beginning until I noticed I was using the X-Content-Security-Policy which doesn't work under Chrome but Content-Security-Policy did. As you mentioned the other one works with IE.

Used this in .htaccess:

# Loading piwik.js from different domain (apache.piwik)
Header set Content-Security-Policy "default-src 'self'; script-src 'self' http://apache.piwik; style-src 'self'; frame-ancestors 'self'; frame-src 'self';"

# Loading piwik.js from same domain as Piwik
Header set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; frame-ancestors 'self'; frame-src 'self';"

With old piwik.js the file was refused to load but with new one worked and I could create a Tracker instance via Piwik.getTracker(...). Inline script did not work, got Refused to execute inline script because it violates the following Content Security Policy directive as expected.

Member

tsteur commented Oct 5, 2015

Tested and worked for me. Took me a while to figure out why it didn't work in the beginning until I noticed I was using the X-Content-Security-Policy which doesn't work under Chrome but Content-Security-Policy did. As you mentioned the other one works with IE.

Used this in .htaccess:

# Loading piwik.js from different domain (apache.piwik)
Header set Content-Security-Policy "default-src 'self'; script-src 'self' http://apache.piwik; style-src 'self'; frame-ancestors 'self'; frame-src 'self';"

# Loading piwik.js from same domain as Piwik
Header set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; frame-ancestors 'self'; frame-src 'self';"

With old piwik.js the file was refused to load but with new one worked and I could create a Tracker instance via Piwik.getTracker(...). Inline script did not work, got Refused to execute inline script because it violates the following Content Security Policy directive as expected.

@fhemberger

This comment has been minimized.

Show comment
Hide comment
@fhemberger

fhemberger Oct 5, 2015

Contributor

@tsteur If you use default-src, you don't need to specify the other *-src if they all use the same value.

CSP might have an impact on 3rd party plug-ins, as they may include files from a CDN or other external resources. So this change should be documented clearly.

Contributor

fhemberger commented Oct 5, 2015

@tsteur If you use default-src, you don't need to specify the other *-src if they all use the same value.

CSP might have an impact on 3rd party plug-ins, as they may include files from a CDN or other external resources. So this change should be documented clearly.

@tsteur

This comment has been minimized.

Show comment
Hide comment
@tsteur

tsteur Oct 5, 2015

Member

I only tested for piwik.js so far. Piwik itself uses lots of inline-script and I think Angular requires eval to work etc. We should definitely mention that when a website uses other 3rd party plugins or a CDN they might have to whitelist further domains etc.

Member

tsteur commented Oct 5, 2015

I only tested for piwik.js so far. Piwik itself uses lots of inline-script and I think Angular requires eval to work etc. We should definitely mention that when a website uses other 3rd party plugins or a CDN they might have to whitelist further domains etc.

@tsteur

This comment has been minimized.

Show comment
Hide comment
@tsteur

tsteur Oct 8, 2015

Member

FAQ could be something like this:

Is the Piwik JavaScript Tracker CSP (Content Security Policy) compatible and how do I set it up?

Yes, Piwik can be used with CSP. However, you cannot use the standard tracking code generated by the Tracking Code Generator in the Piwik UI as it is not allowed to use inline scripts when having CSP enabled. CSP is a security concept to prevent cross-site scripting (XSS) attacks as well as related attacks.

Setting up the JavaScript Tracker

Instead make sure to put the tracking code into files like this:

<script src="http://example.com/piwik/piwik.js" async defer>
<script src="http://example.com/tracking.js">

The file piwik.js should be loaded from your Piwik server and tracking.js should contain the actual tracking calls like this:

var idSite = 1;
var piwikTrackingApiUrl = 'http://example.com/piwik/piwik.php';

var _paq = _paq || [];  
_paq.push(['setTrackerUrl', piwikTrackingApiUrl]);
_paq.push(['setSiteId', idSite]);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);  

Make sure to specify the correct idSite if needed and to replace the Piwik Tracking API URL. You can build this URL by appending /piwik.php to your Piwik domain.

Configuring Content-Secruity-Policy

If you load piwik.js from a different domain make sure to allow the Piwik domain like this: script-src 'self' http://example.com. If you load third party JavaScript files or if you have a CDN you might have to add even more domains to the whitelist.

An example response header looks like this:

Header set Content-Security-Policy "default-src 'self'; script-src 'self' http://example.com; style-src 'self'; frame-ancestors 'self'; frame-src 'self';"

If CSP should work in all browsers you might have to add further headers. At the time of writing this article you might as well need to set X-WebKit-CSP for Safari and X-Content-Security-Policy for Internet Explorer support. Read more about Content Secrutiy Policy.

Member

tsteur commented Oct 8, 2015

FAQ could be something like this:

Is the Piwik JavaScript Tracker CSP (Content Security Policy) compatible and how do I set it up?

Yes, Piwik can be used with CSP. However, you cannot use the standard tracking code generated by the Tracking Code Generator in the Piwik UI as it is not allowed to use inline scripts when having CSP enabled. CSP is a security concept to prevent cross-site scripting (XSS) attacks as well as related attacks.

Setting up the JavaScript Tracker

Instead make sure to put the tracking code into files like this:

<script src="http://example.com/piwik/piwik.js" async defer>
<script src="http://example.com/tracking.js">

The file piwik.js should be loaded from your Piwik server and tracking.js should contain the actual tracking calls like this:

var idSite = 1;
var piwikTrackingApiUrl = 'http://example.com/piwik/piwik.php';

var _paq = _paq || [];  
_paq.push(['setTrackerUrl', piwikTrackingApiUrl]);
_paq.push(['setSiteId', idSite]);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);  

Make sure to specify the correct idSite if needed and to replace the Piwik Tracking API URL. You can build this URL by appending /piwik.php to your Piwik domain.

Configuring Content-Secruity-Policy

If you load piwik.js from a different domain make sure to allow the Piwik domain like this: script-src 'self' http://example.com. If you load third party JavaScript files or if you have a CDN you might have to add even more domains to the whitelist.

An example response header looks like this:

Header set Content-Security-Policy "default-src 'self'; script-src 'self' http://example.com; style-src 'self'; frame-ancestors 'self'; frame-src 'self';"

If CSP should work in all browsers you might have to add further headers. At the time of writing this article you might as well need to set X-WebKit-CSP for Safari and X-Content-Security-Policy for Internet Explorer support. Read more about Content Secrutiy Policy.

@tsteur tsteur assigned mattab and unassigned tsteur Oct 8, 2015

@mattab

This comment has been minimized.

Show comment
Hide comment
@mattab
Member

mattab commented Oct 9, 2015

Thanks, that's a useful and informative FAQ content. Added at: Is the Piwik JavaScript Tracker CSP (Content Security Policy) compatible and how do I set it up?

@mattab mattab closed this Oct 9, 2015

@mattab mattab assigned tsteur and unassigned mattab Oct 9, 2015

@Rudloff

This comment has been minimized.

Show comment
Hide comment
@Rudloff

Rudloff Feb 27, 2018

This issue has been closed but AFAICT the Matomo admin still doesn't have a CSP.

It is a good practice to return a Content-Security-Policy header as it prevents different types of XSS attacks.
I know Matomo still uses inline scripts but we can allow them in the CSP and IMHO having a loose CSP is better than no CSP at all.

Here is what we used on our server:

Content-Security-Policy: default-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' data:

Here is what it means:

  • By default only allow resources from the same domain.
  • Don't allow objects and embeds.
  • Only allow styles from the same domain or from inline styles.
  • Only allow scripts from the same domain, from inline scripts or from eval() calls.
  • Only allow images from the same domain or from data: URLs.

It's also a good idea to define the following headers:

X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY

Rudloff commented Feb 27, 2018

This issue has been closed but AFAICT the Matomo admin still doesn't have a CSP.

It is a good practice to return a Content-Security-Policy header as it prevents different types of XSS attacks.
I know Matomo still uses inline scripts but we can allow them in the CSP and IMHO having a loose CSP is better than no CSP at all.

Here is what we used on our server:

Content-Security-Policy: default-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' data:

Here is what it means:

  • By default only allow resources from the same domain.
  • Don't allow objects and embeds.
  • Only allow styles from the same domain or from inline styles.
  • Only allow scripts from the same domain, from inline scripts or from eval() calls.
  • Only allow images from the same domain or from data: URLs.

It's also a good idea to define the following headers:

X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
@fhemberger

This comment has been minimized.

Show comment
Hide comment
@fhemberger

fhemberger Feb 27, 2018

Contributor

Please never use CSP with unsafe-inline or unsafe-eval, it de facto eliminates XSS protection. Instead, generate nonce- or sha265- hashes to explicitly whitelist inline code snippets (see: https://content-security-policy.com/#source_list):

Example:


$nonce = uniqid();
header("Content-Security-Policy: … script-src 'nonce-" . $nonce . "'"); 

//
echo '<script nonce="' . $nonce . '">alert("hello world")</script>'
Contributor

fhemberger commented Feb 27, 2018

Please never use CSP with unsafe-inline or unsafe-eval, it de facto eliminates XSS protection. Instead, generate nonce- or sha265- hashes to explicitly whitelist inline code snippets (see: https://content-security-policy.com/#source_list):

Example:


$nonce = uniqid();
header("Content-Security-Policy: … script-src 'nonce-" . $nonce . "'"); 

//
echo '<script nonce="' . $nonce . '">alert("hello world")</script>'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment