/**
* Plugin Name: CSP-ANTS&ST
* Description: Add a nonce to each script and style tags, and set those nonces in CSP header
* Version: 1.1.1
* Requires at least: 5.9
* Requires PHP: 7.3
* Author: Pascal CESCATO
* Author URI: https://pascalcescato.gdn/
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
*/
add_action('send_headers', function () {
if (is_admin()){
header("Content-Security-Policy: upgrade-insecure-requests");
return;
}
//เลือก page ที่ไม่ต้องการให้ CSP ทำงาน
if (is_page(['cd-key'])){
header("Content-Security-Policy: upgrade-insecure-requests");
return;
}
if (function_exists('litespeed_autoload')):
// lscache version
function cspantsst_cspantsst_lscwp_check ( $content ) {
$uris = implode ( ' ', cspantsst_search_for_sources ( $content ) );
$sha256_csp = cspantsst_search_for_events ( $content );
$nonces = [];
$content = preg_replace_callback ( '#<script.*?\>#', function ( $matches ) use ( &$nonces ) {
$nonce = wp_create_nonce ( $matches[ 0 ] );
$nonces[] = $nonce;
return str_replace ( '<script', "<script nonce='{$nonce}'", $matches[ 0 ] );
}, $content );
$content = preg_replace_callback ( '#<style.*?\>#', function ( $matches ) use ( &$nonces ) {
$nonce = wp_create_nonce ( $matches[ 0 ] );
$nonces[] = $nonce;
return str_replace ( '<style', "<style nonce='{$nonce}'", $matches[ 0 ] );
}, $content );
$nonces_csp = array_reduce ( $nonces, function ( $header, $nonce ) {
return "{$header} 'nonce-{$nonce}'";
}, '' );
header ( sprintf ( "Content-Security-Policy: base-uri 'self' %1s data:; object-src 'none'; script-src https:%2s %3s 'strict-dynamic'; frame-ancestors 'none'; ", $uris, $nonces_csp, $sha256_csp ));
return $content;
}
add_filter ( 'litespeed_buffer_after', 'cspantsst_cspantsst_lscwp_check', 0 );
else:
// otherwise
add_action ( 'template_redirect', function () {
ob_start ( function ( $output ) {
$uris = implode ( ' ', cspantsst_search_for_sources ( $output ) );
$sha256_csp = cspantsst_search_for_events ( $output );
$nonces = [];
$output = preg_replace_callback ( '#<script.*?\>#', function ( $matches ) use ( &$nonces ) {
$nonce = wp_create_nonce ( $matches[ 0 ] );
$nonces[] = $nonce;
return str_replace ( '<script', "<script nonce='{$nonce}'", $matches[ 0 ] );
}, $output );
$output = preg_replace_callback ( '#<style.*?\>#', function ( $matches ) use ( &$nonces ) {
$nonce = wp_create_nonce ( $matches[ 0 ] );
$nonces[] = $nonce;
return str_replace ( '<style', "<style nonce='{$nonce}'", $matches[ 0 ] );
}, $output );
$header = '';
$nonces_csp = array_reduce ( $nonces, function ( $header, $nonce ) {
return "{$header} 'nonce-{$nonce}'";
}, '' );
header ( sprintf ( "Content-Security-Policy: base-uri 'self' %1s data:; object-src 'none'; script-src https:%2s %3s 'strict-dynamic'; frame-ancestors 'none';", $uris, $nonces_csp, $sha256_csp ) );
return $output;
} );
} );
endif;
function cspantsst_search_for_events ( $output ) {
$sha256 = array ();
preg_match_all ( '/onload="(?<onload>[^"]+)"|onclick="(?<onclick>[^"]+)"/', $output, $matches );
foreach ( $matches[ 'onload' ] as $match ):
if ( !empty ( $match ) )
$sha256[] = base64_encode ( hash ( 'sha256', $match, true ) );
endforeach;
foreach ( $matches[ 'onclick' ] as $match ):
if ( !empty ( $match ) )
$sha256[] = base64_encode ( hash ( 'sha256', $match, true ) );
endforeach;
if ( class_exists ( 'autoptimizeConfig' ) ):
$sha256[] = base64_encode ( hash ( 'sha256', "this.onload=null;this.media='all';", true ) );
endif;
$header_sha256 = "'unsafe-hashes'";
$sha256_csp = array_reduce ( $sha256, function ( $header, $sha256_item ) {
return "{$header} 'sha256-{$sha256_item}'";
}, '' );
if ( !empty ( $sha256_csp ) )
$sha256_csp = $header_sha256 . $sha256_csp;
return $sha256_csp;
}
function cspantsst_search_for_sources ( $string ) {
$result = array ();
if ( strpos ( $string, 'https://secure.gravatar.com/avatar/' ) ):
$result[] = 'https://secure.gravatar.com/avatar/';
endif;
if ( strpos ( $string, 'https://fonts.googleapis.com/' ) ):
$result[] = 'https://fonts.googleapis.com/';
endif;
if ( strpos ( $string, 'https://maxcdn.bootstrapcdn.com/' ) ):
$result[] = 'https://maxcdn.bootstrapcdn.com/';
endif;
return $result;
}
});