@lchandelier opened this Issue on May 19th 2017

I've setted up Piwik like you suggest in you FAQ. However, to be able to use it, I have to allow script-src 'unsafe-inline', which I don't want.

Will you make an enhancement to avoid this?

@godofdream commented on May 20th 2017

you could use 'nonce-myrandomstring' or move the snippet into an external js file

@lchandelier commented on May 22nd 2017

My piwik.js file is on my server and the snippet is already in an external file. I've tried to add the nonce on it but I still have the issue.

@mattab commented on June 21st 2017 Member

Hi @mchandelier do you confirm that our instructions at https://piwik.org/faq/general/faq_20904/ are outdated and that it doesn't just work?

@lchandelier commented on June 21st 2017

Hi @mattab,
It doesn't work for me. The only exception I have from the FAQ is that piwik.js is loaded from the same domain. I may do something wrong but I really don't see what.

@mattab commented on June 22nd 2017 Member

Ok we will need to investigate.

If anyone knows about CSP feel free to take a look (Pull request welcome!).

@mbarbey commented on August 15th 2017

Hi @mattab,
Did you have some news for this problem ?

I am using the piwik script in an external file too to prevent having any inline js code in my pages, and I am encountering the same problem as @mchandelier.

Do you have an idea why the piwik script, which is embedded in an external script, require using script-src 'unsafe-inline' ?

@mattab commented on June 28th 2019 Member

We also got another feedback today on the CSP FAQ:

Here was the feedback:

I do not understand this guide. Based on this guide I cannot make Matomo CSP-compatible.
Where should I place this script tags? Head or body? Footer?
Why do I need two files? Why can't I just have tracking.js and paste there the normal tracking code?

@frjo commented on January 16th 2020

I followed the instructions in https://matomo.org/faq/general/faq_20904/ and it seems to be working. I use this policy on my server.

Header set Content-Security-Policy "default-src 'self'; \
  object-src 'none'; \
  script-src 'self' https://matomo.example.org"

See for example this site: https://xdeb.org/.

I have implemented this in my Hugo theme frjo/hugo-theme-zen.

@daniol commented on June 21st 2020

It would be better to supply the sideID and other parameters via URL parameters to the tracking script. This way would be 100% CSP-compliant without the need of using a second JS file.

The matomo script would read this attributes from document.currentScript and build the _paq object.

<script src="https://example.com/matomo.js?setSiteId=1&trackPageView&enableLinkTracking"></script>

document.currentScript.src -> outputs https://example.com/matomo.js?setSiteId=1&trackPageView&enableLinkTracking

The parameters can be parsed via URLSearchParams an transformed to _paq within 5 lines of code.

const urlParams = new URLSearchParams(document.currentScript.src.substr(document.currentScript.src.indexOf('?')));
for(const entry of urlParams.entries()) {
    if(entry[1] !== undefined) _paq.push([entry[0], entry[1]]);
    else _paq.push([entry[0]]);

Here for an IE polyfill: https://github.com/amiller-gh/currentScript-polyfill

@ixbarbarbar commented on August 15th 2020

Hi all,
I see many tickets on the CSP and apparently only this one is always opened.

On the admin interface, there are many usage of the inline script and a usage also of eval (I see another ticket for the eval but apparently it was close with the correction).

The more easy patch is to use nonce base64 encode for each line where JS inline called (also for css).
I see that already a module to generate a nonce but not for the same function.

Example of code can be added on the core\Twig.php (maybe another place is better...)

class PiwikTwigNonceJs extends \Twig_Extension {
    private $nonce;

     * Generates a random nonce value in base64.
     * <a class='mention' href='https://github.com/return'>@return</a> string
    public function getNonce() : String
        // Only is nonce is null
        if (!$this->nonce) {
            $this->nonce = base64_encode(random_bytes(20));

        return $this->nonce;

     * <a class='mention' href='https://github.com/return'>@return</a> array
    public function getFunctions()
        return [
            new Twig_SimpleFunction('csp_nonce', [$this, 'getNonce']),

// @ the end of the Twig class
$this->twig->addExtension(new PiwikTwigNonceJs());

Modify the template file to add the meta at the begin of the

(example on plugins/Morpheus/templates/layout.twig)
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'nonce-{{ csp_nonce() }}';">

And each template contains the script inline like plugins/Morpheus/templates/_jsGlobalVariables.twig

<script type="text/javascript" nonce="{{ csp_nonce() }}">
@perdittmann commented on February 11th 2021

Hello everyone,
I am still struggling to get my Matomo installation (on a shared hosting server) working with a CSP in place that does not include script-src 'unsafe-inline' and 'unsafe-eval' (which to my understanding would make the whole CSP rather pointless).

ixbarbarbar's solution gave me this:

The following error just broke Matomo (v4.1.1):

Class 'Twig_Extension' not found
in /var/www/example.com/matomo/core/Twig.php line 626

I changed

Is there something I missed?
Many thanks in advance for your help!

@diosmosis commented on February 11th 2021 Member

Hi @perdittmann, that code is using an old version of twig that matomo doesn't use anymore. Instead of the /core/Twig.php changes you made, these changes should work:


can you try them out?

@perdittmann commented on February 12th 2021

Hi @diosmosis, thank you for your help!
I managed to isert the code into the two files you mentioned, and didn't produce a critical error this time. :-)

I updated every instance of

Alas, the admin panel is still blank below the blue header.
I found one script still without the nonce:

    <script type="text/javascript">
    var translations = {"CorePluginsAdmin_NoZipFileSelected": …

(close to the end of the < head >).
I think it is called by {{ includeAssets({"type":"js"}) }} – but so far, I have been able to figure out where the corresponding getJsInclusionDirective is defined.

Am I in luck and you could point me in the right direction again?
Thanks a lot!

@perdittmann commented on February 14th 2021

If there only was a way to search the entire source code … 🤦
I got where I needed to be, but I am out of my depth again.

getJsInclusionDirective() is defined in core/AssetManager.php.
Since it is a PHP file, the twig syntax to add the nonce does not work, and I couldn't figure out how to get to the nonce in PHP.
Do you maybe have an idea? Thanks!

@diosmosis commented on February 14th 2021 Member

hi @perdittmann, you can use grep or a similar tool to find <script elements in the code. I'm also going to ask that you ask future questions about the code base on the forums: https://forum.matomo.org/ as you may not get a response here

@perdittmann commented on February 22nd 2021

(I had just realized I can search the source code right here, that was me being self-deprecating. 😄)
Thanks for the link and for your help. I will try my luck there!

@Ryonez commented on November 30th 2021

Do we have a CSP compliant solution yet?

Powered by GitHub Issue Mirror