Skip to content

Instantly share code, notes, and snippets.

@joshuafredrickson
Created December 5, 2023 01:33
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joshuafredrickson/f0a9101eb7014054a7486f015d68a7f9 to your computer and use it in GitHub Desktop.
Save joshuafredrickson/f0a9101eb7014054a7486f015d68a7f9 to your computer and use it in GitHub Desktop.
Add CSP to WordPress, including nonces for inline scripts
<?php
/**
* Plugin Name: Content Security Policy
* Version: 1.0.0
* Description: Adds a Content-Security-Policy header to all non-admin requests.
* License: GNU General Public License v2
* License URI: http://www.gnu.org/licenses/gpl-2.0.html
* Original Inspiration: https://gist.github.com/westonruter/c8b49406391a8d86a5864fb41a523ae9
*/
namespace App;
use function Roots\add_filters;
/**
* Gets CSP nonce.
*/
function get_nonce(): string
{
static $nonce = null;
if ($nonce === null) {
$nonce = wp_create_nonce('csp');
}
return $nonce;
}
/**
* Gets Strict CSP header value.
*/
function get_csp_header_value(): string
{
return join(
'; ',
// Set your CSP below
[
"font-src 'self' data:",
"frame-src 'none'",
"img-src 'self' data: secure.gravatar.com",
"manifest-src 'self'",
sprintf("script-src-elem 'nonce-%s' 'self'", get_nonce()),
"style-src-elem 'self' 'unsafe-inline'", // Unfortunately, inline CSS is not currently filterable
"object-src 'none'",
"base-uri 'none'" // Note: jQuery can violate this in jQuery.parseHTML() due to <https://github.com/jquery/jquery/issues/2965>.
"report-uri https://{{ your reporting uri }}",
]
);
}
/**
* Adds nonce attribute to script attributes.
*/
add_filters(
['wp_script_attributes', 'wp_inline_script_attributes',],
function (array $attributes): array {
$attributes['nonce'] = get_nonce();
return $attributes;
}
);
/**
* Sends Strict CSP header.
*/
add_action('login_init', function () {
header(sprintf('Content-Security-Policy: %s', get_csp_header_value()));
});
/**
* Send the header on the frontend and in the login screen.
*/
add_filter(
'wp_headers',
static function ($headers) {
$headers['Content-Security-Policy'] = get_csp_header_value();
return $headers;
}
);
@devendrabhandari
Copy link

Will it work for all the styles and scripts added by plugins and themes, as well as the inline scripts added by the theme?

@joshuafredrickson
Copy link
Author

Will it work for all the styles and scripts added by plugins and themes, as well as the inline scripts added by the theme?

✅ Inline scripts
✅ Enqueued scripts
⛔ Inline styles
✅ Enqueued styles

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment