Content Security Policy
- Author
- KD Web
- Version
- 0.0.6
- Requires
- 6.0.0
- Tested
- 6.9.9
- Requires PHP
- 8.0.0
Builds and sends a nonce-based Content-Security-Policy header, with an admin builder covering every CSP directive, sensible defaults so themes/plugins/embeds keep working, and full compatibility with LiteSpeed Cache.
Features
- Full CSP directive builder: all fetch, document, navigation, reporting, sandbox, and Trusted Types directives, with sensible defaults out of the box and a one-click reset back to them.
- Built-in catalog of common integrations (Google Analytics/Tag Manager, Google Fonts, YouTube, Vimeo, Facebook, Twitter/X, Instagram, Google Maps, reCAPTCHA, common CDNs, and more) that can be toggled on/off per site.
- Nonce-based script-src, with automatic nonce injection into scripts registered via wp_add_inline_script() — no code changes needed for well-behaved plugins/themes.
- LiteSpeed Cache aware nonce lifecycle: rotates on a timer and on cache purge by default, or true per-request nonces in Strict mode.
- Automatically allows LiteSpeed Cache's own lazy-load and JS-delay inline scripts (which LiteSpeed injects with no WordPress hook and no nonce of its own) via a hash computed from LiteSpeed's own settings/library files, kept correct automatically as they change.
- Built-in client-side hash calculator for allowlisting any other static inline script/style that can't be nonced — e.g. one echoed outside WordPress's script APIs, or dynamically re-inserted by JavaScript in a way that strips its nonce.
- Optional one-click "Strict style-src" action to remove 'unsafe-inline' for sites that need to pass a scanner or compliance check (PCI DSS 4.0.1, OWASP, ISO 27001) that flags it — left off by default since it can break WordPress's own inline CSS, but pairs well with LiteSpeed Cache's own CSS-combine optimization.
- Report-Only mode for safely testing a policy before enforcing it. wp-admin is never affected.
How to Use
- Install and activate the plugin.
- Go to Settings → CSP in the WordPress admin dashboard.
- Start in Report-Only mode, then review the Integrations tab for the third-party services your site actually uses.
- Check your browser console for CSP violation reports, adjust directives on the Directive Builder tab as needed, then switch off Report-Only to start enforcing.
Benefits
- Meaningfully reduces XSS risk without breaking day-to-day site functionality.
- No manual header configuration in .htaccess or server config required.
- Designed from the ground up to keep working alongside LiteSpeed's full-page cache.
Changelog
0.0.6
- Admin UI cleanup: moved the "Auto-nonce WordPress inline scripts" setting and the "Hash a static inline script or style" tool from the top of the General/Directive Builder tabs down to the bottom of the Directive Builder tab, so the directive fields themselves are the first thing you see. No functional change.
0.0.5
- Added an opt-in "Remove 'unsafe-inline' from style-src" action on the Directive Builder tab, for sites that need to pass a scanner or compliance check (PCI DSS 4.0.1, OWASP, ISO 27001) that flags it. Left off by default, since removing it site-wide would break WordPress core's own inline CSS out of the box (there's no nonce hook for it) — this is a deliberate, documented choice rather than a change to the shipped defaults.
- Documented the LiteSpeed Cache "CSS Combine External and Inline" pairing directly in that action's help text: enabling it sweeps most inline <style> blocks into an external combined file (confirmed against LiteSpeed's own source), which is what makes dropping unsafe-inline viable — with the caveats that it doesn't cover inline style="" attributes, and a per-page critical-CSS chunk from LiteSpeed's "Load CSS Asynchronously" feature is deliberately excluded from combine.
0.0.4
- Correction to 0.0.3: the script that kept getting blocked wasn't a Gravity Forms script after all — it was LiteSpeed Cache's own lazy-load bootstrap script, which LiteSpeed injects by string-replacing it straight into the rendered page HTML, with no WordPress hook at all for a third-party plugin to add a nonce to it. Confirmed directly against LiteSpeed Cache's own source and against a live site.
- Added automatic hash-source allowlisting for LiteSpeed Cache's lazy-load and JS-delay inline scripts. The script content is recomputed from LiteSpeed's own on-disk library files and its public litespeed_lazyload_threshold filter (not from anything on the page itself), so the hash stays correct automatically even if the threshold setting or the library file changes, without the admin needing to hand-maintain it. Verified byte-for-byte against a live site's actual blocked script.
- Added a status pill showing whether any LiteSpeed scripts were auto-allowed this way.
0.0.3
- Added guidance and a client-side "hash a static inline script or style" tool on the Directive Builder tab, for scripts/styles that keep getting blocked even though they already have a matching nonce.
- Explained the underlying cause in the plugin's own UI: this typically happens when a script is inserted into the page dynamically by JavaScript after the initial load (common with AJAX-based Gravity Forms, for example) — browsers deliberately hide a nonce from JavaScript/DOM inspection once it's been used, so a script re-created or re-executed by client-side code often loses it even though the original HTML had one. A sha256- hash isn't affected by this, since it matches by exact content rather than by attribute — and the browser's own console message for a blocked script already shows the exact hash it needs.
0.0.2
- Fixed: inline <style> elements were being blocked because WordPress has no core hook to nonce them (the wp_inline_style_attributes filter this relied on doesn't actually exist) — style-src/style-src-elem now use 'unsafe-inline' instead of a nonce.
- Fixed: inline event handler attributes (onclick etc.) were blocked by default — script-src-attr now defaults to 'unsafe-inline', since nonces can never cover attributes per the CSP spec.
- Fixed: navigate-to could be emitted twice in the header due to a redundant settings path.
- Removed the Compatible/Strict preset system in favour of a single set of sensible defaults, with a "Reset directives to defaults" button on the Directive Builder tab.
- Removed the "Apply in wp-admin" setting — the CSP header is now never sent in wp-admin.
- Merged the LiteSpeed & Nonce tab into General; merged the Advanced tab's fields into the Directive Builder tab, grouped by directive category (this also fills in the previously-empty Other and Reporting sections).
- Reordered tabs: General, Integrations, Directive Builder, Preview.
0.0.1
Released
Download
Back