Skip to content

Instantly share code, notes, and snippets.

@joshuafredrickson
Last active April 30, 2025 23:34
Show Gist options
  • Save joshuafredrickson/f0a9101eb7014054a7486f015d68a7f9 to your computer and use it in GitHub Desktop.
Save joshuafredrickson/f0a9101eb7014054a7486f015d68a7f9 to your computer and use it in GitHub Desktop.

Revisions

  1. joshuafredrickson revised this gist Dec 12, 2024. 1 changed file with 9 additions and 10 deletions.
    19 changes: 9 additions & 10 deletions csp-mu-plugin.php
    Original file line number Diff line number Diff line change
    @@ -1,17 +1,17 @@
    <?php
    /**
    * Plugin Name: Content Security Policy
    * Version: 1.0.0
    * Version: 1.0.1
    * Description: Adds a Content-Security-Policy header to all non-admin requests.
    * License: GNU General Public License v2
    * Requires PHP: 8.1
    * Requires at least: 5.7.0
    * 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.
    */
    @@ -42,7 +42,7 @@ function get_csp_header_value(): string
    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>.
    "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 }}",
    ]
    );
    @@ -51,13 +51,12 @@ function get_csp_header_value(): string
    /**
    * Adds nonce attribute to script attributes.
    */
    add_filters(
    ['wp_script_attributes', 'wp_inline_script_attributes',],
    function (array $attributes): array {
    foreach (['wp_script_attributes', 'wp_inline_script_attributes'] as $hook) {
    add_filter($hook, function (array $attributes): array {
    $attributes['nonce'] = get_nonce();
    return $attributes;
    }
    );
    });
    }

    /**
    * Sends Strict CSP header.
  2. joshuafredrickson created this gist Dec 5, 2023.
    78 changes: 78 additions & 0 deletions csp-mu-plugin.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,78 @@
    <?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;
    }
    );