Created
December 5, 2023 01:33
-
-
Save joshuafredrickson/f0a9101eb7014054a7486f015d68a7f9 to your computer and use it in GitHub Desktop.
Add CSP to WordPress, including nonces for inline scripts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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; | |
} | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
✅ Inline scripts
✅ Enqueued scripts
⛔ Inline styles
✅ Enqueued styles