Where to add Content Security Policy (CSP)?

12 posts by 3 authors in: Forums > CMS Builder
Last Post: April 12, 2024   (RSS)

By mark99 - October 23, 2023

Where is the best place to add a CSP into CMS Builder so that it applies across the system? I usually include it via header() calls inside PHP (or an 'include' call to a CSP.php file that contains those headers) as the .htaccess approach doesn't work for PHP on our server (it only impacts SHTML/HTML/CGI).

By Dave - October 23, 2023

Hi Mark, 

You could put them in /cmsb/lib/menus/header.php and if you email them over to me (or post) I can include them in the next release if they'd be helpful to others.  

Dave Edis - Senior Developer
interactivetools.com

By mark99 - October 24, 2023

I'm not sure I'd recommend including CSP into CMSBuilder by default, as it's one of those things that you need to tailor to a specific site due to the risk of breaking things. In my case, I'm just using a simplified set to be compliant, and it's not a particularly strong or secret batch of settings. The ones I'm using - after a lot of trial and error - are:

header('X-Frame-Options: SAMEORIGIN');

header("X-XSS-Protection: 1; mode=block");

header("X-Content-Type-Options: nosniff");

header("Content-Security-Policy: default-src * data: blob:; script-src https: 'unsafe-inline' 'unsafe-eval'; style-src https: 'unsafe-inline'; img-src https: http://www.YOURSITE.com http://*.YOURSITESUBDOMAIN.com data: blob:; frame-src https:; base-uri *; worker-src * https: blob:;");

header("Permissions-Policy: camera=(), geolocation=(), magnetometer=(), microphone=(), midi=(), payment=(), usb=(), hid=()");

But what would be handy is if we could set them in CMSBuilder without needing to edit core files that may change with each update of the CMS. For example, adding them into the config file or via the admincp may be handy.

By Djulia - October 24, 2023 - edited: October 24, 2023

Hi Mark,

Interesting post!

Personally, I use my CSP in an .htaccess file (Apache). I do not have access to the security.conf file.

<ifModule mod_headers.c>
  Header set X-XSS-Protection "1; mode=block"
  Header always append X-Frame-Options SAMEORIGIN
  Header set X-Content-Type-Options: "nosniff"
  Header set Content-Security-Policy "default-src 'self' 'unsafe-inline' mystats.mysite.com"
</ifModule>

Thanks,
Djulia

By mark99 - October 25, 2023

Sadly on our Ionos (1&1) server the .htaccess method doesn't touch .php files, otherwise I'd be using that too.

By Djulia - October 25, 2023

In the documentation they refer to the .htaccess file. Are you on a particular offer?
https://www.ionos.com/digitalguide/server/security/content-security-policy-how-websites-are-becoming-safer/

By mark99 - October 25, 2023

I believe it's down to the fact that they install PHP with FastCGI, which in this case means that any 'headers' for CSP added via .htaccess will only touch older server files like .html and .cgi. Not much good if you want to apply it in PHP, where the alternative is to add the headers directly into the PHP programme itself - usually in a config file or a key file that the system always needs to call (e.g. init.php). Took me a lot of trial and error to eventually figure this one out. Tools like this helped:

https://cspvalidator.org

As usual with Ionos, the information they put on their own website often doesn't accurately reflect the different setups on the servers they sell to consumers.

By Dave - October 25, 2023

Hi All, 

Let me know if there are some default policies we could add that would help.  We'll also work to make things more compliant and strict as we continue to update the codebase.  

In the meantime, I've made it possible to add or modify the headers with a plugin for the next release.  Here's how to apply that patch if you'd like to do that now.

In /lib/headers.php find this block of code at the top

// show headers - prevent caching of CMS pages
header('Content-type: text/html; charset=utf-8');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache');
header('Expires: 0');

Replace it with this:

// headers: prevent caching of CMS pages
$headers = [];
$headers[] = 'Content-type: text/html; charset=utf-8';
$headers[] = 'Cache-Control: no-store, no-cache, must-revalidate, max-age=0';
$headers[] = 'Pragma: no-cache';
$headers[] = 'Expires: 0';

$headers = applyFilters('headers', $headers); // Allow plugins to modify headers
array_map('header', $headers); // Call PHP header() for each header
header_remove('X-Powered-By'); // Security: Prevent information disclosure, eg: X-Powered-By: PHP/8.0.11

Then add this plugin (modify as needed): 

<?php
/*
Plugin Name: CSP Headers
Description: Add CSP Headers (requires CMSB 3.63 or a patch)
Version: 1.00
*/

// Plugin Actions
addFilter('headers', 'addCspHeaders', null, 1);

//
function addCspHeaders($headers) {
    $headers[] = "X-Frame-Options: SAMEORIGIN";
    $headers[] = "X-XSS-Protection: 1; mode=block";
    $headers[] = "X-Content-Type-Options: nosniff";
    $headers[] = "Content-Security-Policy: default-src * data: blob:; script-src https: 'unsafe-inline' 'unsafe-eval'; style-src https: 'unsafe-inline'; img-src https: http://www.YOURSITE.com http://*.YOURSITESUBDOMAIN.com data: blob:; frame-src https:; base-uri *; worker-src * https: blob:;";
    $headers[] = "Permissions-Policy: camera=(), geolocation=(), magnetometer=(), microphone=(), midi=(), payment=(), usb=(), hid=()";

    return $headers;
}

Hope that helps!  Let me know if that works for you.

Dave Edis - Senior Developer
interactivetools.com

By Djulia - October 26, 2023

Hi Dave,

I just tested your plugin and everything works fine for me. Thanks!

@Mark

Thanks for this link! I also use this site :
https://securityheaders.com

By mark99 - October 26, 2023

Nice work, thanks Dave and Djulia.