Kirby3 Security Headers - Best practice headers, Nonce, CSP and Feature Policies

I am creating posts for my plugins to make it easier to find them using the forum search and not just the docs search.

This plugins comes with sensible defaults but lets you adjust the headers using the config.

/site/config/config.php

<?php
return [
    'bnomei.securityheaders.headers' => [
        "X-Powered-By" => "", // unset
        "X-Frame-Options" => "SAMEORIGIN",
        "X-XSS-Protection" => "1; mode=block",
        "X-Content-Type-Options" => "nosniff",
        "strict-transport-security" => "max-age=31536000; includeSubdomains",
        "Referrer-Policy" => "no-referrer-when-downgrade",
        "Permissions-Policy" => 'interest-cohort=()', // flock-off,
        // ... FEATURE POLICIES
    // other options...
];

loader
To define the Content security policies (CSP) you can use a json/yaml file (based on the default that comes with the plugin) or…

setter
… use a callback to define csp entries right within the config. Within the setter you can also define custom nonces if you need some.

export apache/nginx
You can also export your configurations for apache/nginx if you prefer to apply them there instead dynamically with kirby.

1 Like

the export apache/nginx is also necessary if you use a static site generator SSG like the brand new GitHub - getkirby/staticache: Static site performance on demand plugin (might be moved to core).

With the new version of my Content Security Policy (CSP) Header plugin, securing your website is easier than ever. I upgraded the underlying library and tested the plugin against the alpha version of Kirby v5.

It might not have been evident from the posts above, but the plugin has almost “zero config.” You install it and define the rules you need in a single config callback. Done!

/site/config/config.php

<?php
return [
    'bnomei.securityheaders.setter' => function ($instance) {
        // https://github.com/paragonie/csp-builder
        // #build-a-content-security-policy-programmatically
        /** @var ParagonIE\CSPBuilder\CSPBuilder $csp */
        $csp = $instance->csp();
        
        // allowing all inline scripts and styles is
        // not recommended, try using nonces instead
        // $csp->setAllowUnsafeEval('script-src', true);
        // $csp->setAllowUnsafeInline('script-src', true);
        // $csp->setAllowUnsafeInline('style-src', true);
        
        // youtube
        $csp->addSource('frame', 'https://www.youtube.com');
        $csp->addSource('frame', 'https://youtube.com');
        $csp->addSource('image', 'https://ggpht.com');
        $csp->addSource('image', 'https://youtube.com');
        $csp->addSource('image', 'https://ytimg.com');
        $csp->addSource('script', 'https://google.com');
        $csp->addSource('script', 'https://youtube.com');

        // vimeo
        $csp->addSource('frame', 'player.vimeo.com');
        $csp->addSource('image', 'i.vimeocdn.com');
        $csp->addSource('script', 'f.vimeocdn.com');
        $csp->addSource('source', 'player.vimeo.com');
        $csp->addSource('style', 'f.vimeocdn.com');
    },
    // other options...
];