WP Manifestindependent plugin directory
manifest / security / wordpress-security-helper

PW Security Helpers

A plugin that help you toggle common security hardening features

by Tyrus Christiana · github.com/hawkspook/wordpress-security-helper · website

0stars
0forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/hawkspook/wordpress-security-helper/archive/refs/heads/main.zip

PW Security Helpers is a lightweight WordPress plugin that adds opt-in hardening controls to common attack surfaces and delivers optional HTTP security headers. The plugin is designed to be safe-by-default, requiring administrators to explicitly enable each mitigation so it plays well with a wide variety of site configurations.

Features

  • Toggle REST API user enumeration protections that block ALL access to /wp-json/wp/v2/users.
  • Prevent classic /?author=1 probing for author archives.
  • Disable the legacy xmlrpc.php endpoint when it is not required.
  • Restrict the REST API to authenticated users only.
  • NEW: Hide WordPress Version - Remove version information from meta tags, feeds, and block readme files.
  • NEW: Hide Plugin/Theme Versions - Remove version query strings from CSS/JS files.
  • Enable and configure a suite of HTTP security headers including:
    • Strict-Transport-Security
    • Content-Security-Policy
    • X-Frame-Options
    • X-Content-Type-Options
    • Referrer-Policy
    • Permissions-Policy
  • NEW: CSP Builder - Automated Content Security Policy generator:
    • Scan multiple pages to discover all resources (scripts, styles, images, fonts, etc.)
    • Visual interface to select which resources to allow without writing CSP code
    • Automatic nonce generation for inline scripts and styles
    • Report-Only mode for safe testing before enforcement
    • Real-time policy preview with copy-to-clipboard functionality
  • Tabbed settings page for easy navigation between core protections, security headers, and CSP builder.

Requirements

  • WordPress 6.4 or newer (tested up to the latest stable release at the time of writing).
  • Administrator capability to manage site settings.

Installation

  1. Copy the plugin directory into your WordPress installation under wp-content/plugins/pw-security-helpers.
  2. Log in to the WordPress admin dashboard and activate PW Security Helpers from the Plugins screen.

Usage

Core Protections & Security Headers

  1. Navigate to Settings → PW Security Helpers.
  2. Use the Core Protections tab to enable REST and XML-RPC hardening features as needed.
  3. Switch to the Security Headers tab to enable the headers appropriate for your site. Adjust directive values before enabling to avoid breaking legitimate functionality.
  4. Save changes after updating each tab.

CSP Builder (Content Security Policy Generator)

The CSP Builder provides a no-code solution for creating Content Security Policies:

  1. Navigate to Settings → PW Security Helpers → CSP Builder.
  2. Add URLs to scan:
    • Enter the URLs of pages you want to scan (homepage, key pages, posts, etc.)
    • Click "Add URL" for each page
    • Click "Scan Now" to analyze all added pages
  3. Review discovered resources:
    • The scanner will find all scripts, styles, images, fonts, and other resources used on your pages
    • Resources are organized by CSP directive type (script-src, style-src, etc.)
    • Use "Select All" / "Deselect All" buttons for quick management
  4. Configure inline code handling:
    • If inline scripts or styles are detected, enable "Generate nonces" for secure handling
    • Nonces are automatically added to enqueued scripts and styles
  5. Choose deployment mode:
    • Report-Only (recommended): Logs violations without blocking them - perfect for testing
    • Enforce: Actively blocks policy violations
  6. Review and deploy:
    • Preview the generated policy in real-time
    • Check "Use this generated policy" to activate it
    • The generated policy will override any manual CSP settings in the Security Headers tab
  7. Monitor and refine:
    • Start in Report-Only mode and monitor your site
    • Adjust selections if needed
    • Switch to Enforce mode when confident

Notes on Security Headers

  • Strict-Transport-Security is automatically skipped on non-HTTPS requests to avoid trapping users on HTTP-only environments.
  • Use caution when enabling Content-Security-Policy or Permissions-Policy; incorrect directives can prevent required scripts or browser features from functioning.
  • The plugin does not automatically add preload entries for HSTS. Submit your domain to hstspreload.org when you are confident the configuration is correct.
  • Tip: Use the CSP Builder tab instead of manually configuring Content-Security-Policy - it's much easier and less error-prone.

Notes on Version Hiding

IMPORTANT: Version hiding is "security through obscurity" - it does NOT fix vulnerabilities!

What it does:

  • Slows down automated reconnaissance by hiding version information
  • Makes it slightly harder for attackers to identify vulnerable versions
  • Removes WordPress version from HTML meta tags and RSS feeds
  • Blocks access to readme.html and license.txt files
  • Removes ?ver=X.X.X query strings from CSS/JS files

What it does NOT do:

  • Fix security vulnerabilities in WordPress or plugins
  • Prevent determined attackers from fingerprinting your site
  • Replace the need for regular security updates
  • Protect against zero-day exploits

Best practices:

  1. Always keep WordPress and plugins updated - This is your primary defense
  2. Use version hiding as ONE layer in a defense-in-depth strategy
  3. Combine with other security measures (firewall, login protection, etc.)
  4. Be aware that removing version query strings may affect browser caching
  5. Determined attackers can still fingerprint WordPress through file structure, REST API, and other methods

Testing after enabling:

  • Check your site's HTML source for <meta name="generator">
  • Visit your RSS feed and verify no version information
  • Try accessing /readme.html (should return 403 Forbidden)
  • Check browser console for any CSS/JS loading errors

Development

  • Source code is contained in pw-security-helpers.php.
  • Options are stored in the single pwsh_options option entry for easy export.
  • Coding standards follow modern WordPress best practices and sanitization patterns.

Support & Contributions

This plugin is maintained as a helper for personal projects. Bug reports and improvement ideas are welcome; please open an issue or submit a pull request if you have suggestions.

Changelog

Version 2.5.2

  • ENHANCEMENT: Improved debugging and visibility for inline code handling
    • Added comprehensive console logging during scan (shows inline script/style collection)
    • Added debug output in admin UI when WP_DEBUG is enabled (shows database contents)
    • Inline code handling section now always visible after scan (even if no inline content detected)
    • Better error messages when iframe scanning fails (CORS issues)
    • Console shows summary: "Total inline scripts collected: X, Total inline styles collected: X"
    • Debug box shows: inline script/style counts, selected methods, and raw data structure
  • ENHANCEMENT: Improved user feedback
    • Inline handling section shows message if no inline code detected during scan
    • Helps users understand if scanning worked or if inline code was missed
  • Technical details:
    • Console logs show character count for each collected inline script
    • Warns if iframe document cannot be accessed (CORS)
    • Server logs show processing and hash generation when WP_DEBUG_LOG is enabled

Version 2.5.1

  • BUG FIX: Fixed SHA-256 hash generation not working
    • Client-side scanner now properly collects inline script/style content (not just detection)
    • Changed from boolean detection to content arrays that capture actual code
    • Server properly receives inline content from AJAX and generates SHA-256 hashes
    • Hash generation now works correctly: base64_encode(hash('sha256', $content, true))
    • Inline method settings (unsafe-inline/sha256/nonce) now save correctly
    • Fixed data structure mismatch between client and server
  • ENHANCEMENT: Style attribute compatibility handling
    • Detects when inline style attributes (style="...") are present
    • Automatically includes 'unsafe-inline' for styles when attributes detected (SHA-256 doesn't work for attributes)
    • Shows informative notice explaining the limitation
  • Technical details:
    • extractResourcesFromDocument() now returns {resources, inlineScripts, inlineStyles}
    • scanUrlsSequentially() properly merges inline content arrays
    • ajax_save_scan_results() processes inline content and generates hashes
    • Special marker __STYLE_ATTRIBUTES_DETECTED__ tracks style attribute usage

Version 2.5.0

  • MAJOR FEATURE: SHA-256 hash support for inline scripts and styles
    • New option to use SHA-256 hashes instead of 'unsafe-inline' for CSP
    • More secure than 'unsafe-inline' - only allows specific detected scripts/styles
    • No code changes required (unlike nonces)
    • Automatically generates SHA-256 hash for each inline script/style during scan
    • New radio button UI to choose handling method:
      • 'unsafe-inline' (least secure, maximum compatibility)
      • SHA-256 hashes (more secure, no code changes needed)
      • Nonces (most secure, requires code modification)
    • Displays hash table showing all detected inline scripts with preview and hash
    • Copy-to-clipboard button for each hash
    • Hashes automatically added to CSP when SHA-256 method is selected
    • 'unsafe-inline' automatically filtered out when using SHA-256
    • Separate method selection for scripts and styles
    • Backwards compatible - defaults to 'unsafe-inline' for existing installations
  • Technical implementation:
    • Server-side scanner now stores full inline script/style content (not just 100 char preview)
    • Uses PHP's hash('sha256', $content, true) and base64_encode() for hash generation
    • Inline content stored as array with 'preview' and 'hash' keys
    • CSP generation updated to add 'sha256-{hash}' entries for each inline script/style
    • Form submission saves selected method preferences

Version 2.4.4

  • ENHANCEMENT: Improved CSP preview formatting
    • CSP preview now displays in readable multi-line format
    • Added "Content-Security-Policy:" header label at top
    • Each directive on its own indented line
    • Fixed escaped quote characters in copied/displayed policy
    • Better word wrapping for long URLs (uses word-wrap instead of word-break)
    • Makes it easier to read and copy CSP policies

Version 2.4.3

  • ENHANCEMENT: Improved security header test accuracy
    • Tests now check if header value is configured, not just if checkbox is enabled
    • Shows warning "Enabled but no value configured" when header is enabled but missing required value
    • Only shows fail status when header has value configured but isn't being sent
    • Provides clearer guidance on what action to take for each scenario
    • Prevents false failures for headers like Permissions-Policy that require configuration

Version 2.4.2

  • ENHANCEMENT: Security Headers tests now show individual results
    • Broke down single "Security Headers" test into 5 separate tests
    • Each header now shows its own pass/fail/warning status:
      • Strict-Transport-Security (HSTS)
      • X-Frame-Options
      • X-Content-Type-Options
      • Referrer-Policy
      • Permissions-Policy
    • Makes it easier to identify exactly which headers are working
    • Each test shows the actual header value when present

Version 2.4.1

  • BUG FIX: Fixed Test & Verify tab JavaScript errors
    • Corrected data attribute selectors (data-test-id → data-test)
    • Fixed section selection logic to use proper data-group attributes
    • Updated HTML structure to match JavaScript expectations (test-icon → test-status, test-result → test-message)
    • Added missing test-details spans to all test items
    • Added CSS styling for test details display
    • Tests now run and display results correctly

Version 2.4.0

  • NEW FEATURE: Test & Verify Tab
    • Added dedicated "Test & Verify" tab to settings page for diagnostic testing
    • Run real-time tests to verify security settings are actually working
    • Tests all protection categories: Core Protections, Version Hiding, Security Headers, and CSP
    • Visual pass/fail/warning indicators with detailed results
    • Select which test groups to run (all or selective testing)
    • Tests include:
      • REST API user enumeration blocking
      • Author enumeration protection
      • XML-RPC access control
      • REST API authentication requirements
      • WordPress version hiding effectiveness
      • Readme/license file blocking
      • Version string removal from assets
      • Security headers presence and configuration
      • CSP header deployment mode detection
    • Server-side testing using actual HTTP requests to verify protections work in real-world scenarios
    • Helps administrators confirm their security configuration is effective
    • No guesswork - see exactly which protections are active and working

Version 2.1.0

  • NEW FEATURE: Hide WordPress Version
    • Removes WordPress version from HTML meta generator tags
    • Removes version from RSS/Atom feeds
    • Blocks access to /readme.html and /license.txt files (returns 403)
    • Helps slow down automated reconnaissance
  • NEW FEATURE: Hide Plugin/Theme Versions
    • Removes version query strings (?ver=X.X.X) from all CSS/JS files
    • Applies to both WordPress core and plugin/theme assets
    • Warning: May affect browser caching behavior
  • Enhancement: Both features added to Core Protections tab with status indicators
  • Important: These features provide "security through obscurity" - NOT real security
    • Does not fix vulnerabilities
    • Should be used WITH other security measures, not instead of them
    • Regular security updates remain critical

Version 2.3.1

  • NEW FEATURE: Auto-detection and support for Web Workers
    • Added worker-src CSP directive support
    • Automatically includes 'self' blob: for worker-src to allow Web Worker creation
    • Fixes CSP violations when sites use Web Workers (common in modern WordPress plugins/themes)
    • Scanner automatically detects and configures worker-src
    • Added informative UI message explaining worker-src and blob: protocol usage
    • Resolves errors like: "Creating a worker from 'blob:...' violates CSP directive"
  • Technical details:
    • worker-src controls where Web Workers, Service Workers, and Shared Workers can load from
    • blob: protocol is standard for creating workers in modern JavaScript
    • Falls back to script-src if worker-src is not explicitly set
    • Safe and commonly required for WordPress sites with background processing

Version 2.3.0

  • MAJOR IMPROVEMENT: Client-side scanning for complete resource detection
    • Scanner now loads pages in the browser to catch ALL resources (not just initial HTML)
    • Detects JavaScript-loaded resources, AJAX calls, lazy-loaded images, and dynamic content
    • Waits 3 seconds after page load to catch late-loading resources
    • Scans fully-rendered DOM to see exactly what the browser loaded
    • Much more accurate CSP generation for modern WordPress sites with dynamic content
    • Each URL is loaded in a hidden iframe, scanned, then removed
    • Status updates show progress: "Scanning 1 of 3: https://example.com"
  • Technical details:
    • Previous server-side scanning only saw initial HTML via wp_remote_get()
    • New client-side scanning executes JavaScript and waits for full page load
    • Extracts resources from the actual loaded DOM, not just source HTML
    • Handles protocol-relative URLs, data: URIs, blob: URLs, and relative paths correctly

Version 2.2.0

  • MAJOR IMPROVEMENT: CSP Builder now automatically handles WordPress inline content
    • Scanner automatically detects inline scripts and styles
    • Automatically adds 'unsafe-inline' to script-src and style-src when inline content is found
    • Automatically adds data: to font-src for data URI fonts (common in WordPress themes)
    • All discovered resources are now auto-selected after scanning for easier setup
    • Added informative warning explaining why 'unsafe-inline' is needed for WordPress
    • CSP policies now work out-of-the-box without manual configuration
  • Note: While 'unsafe-inline' reduces CSP security, it's required for most WordPress sites. The CSP still provides significant protection by controlling external resource domains.

Version 2.1.3

  • ENHANCEMENT: Improved header sending reliability
    • Added template_redirect hook in addition to send_headers for better compatibility with various hosting environments
    • Added comprehensive debug logging to help troubleshoot header issues
    • Logs show which headers are being sent and when
    • Check wp-content/debug.log (when WP_DEBUG_LOG is enabled) to verify headers are being sent

Version 2.1.2

  • BUG FIX: Fixed Content-Security-Policy headers not being sent
    • CSP Builder's "Use this generated policy" now works independently without requiring Security Headers tab to be enabled
    • Manual CSP in Security Headers tab continues to work as before
    • Simplified internal logic to remove redundant checks
    • Headers are now properly sent when either CSP Builder or manual CSP is enabled

Version 2.1.1

  • SECURITY ENHANCEMENT: CSP Builder now generates more secure policies by default
    • Always adds default-src 'none' as the first directive for explicit allow-listing
    • Automatically filters out data: URIs from frame-src (XSS risk)
    • Sets object-src 'none' by default to block legacy plugins
    • Added security warning in UI when dangerous resources are detected
    • Policy generator now follows security best practices for Content Security Policy

Version 2.0.6

  • SECURITY FIX: REST API User Enumeration blocking now properly blocks ALL access to /wp-json/wp/v2/users
    • Previous version only blocked filtered queries (?search=, ?context=, etc.)
    • Now blocks the entire users endpoint for unauthenticated users
    • Logged-in users can still access individual user data (/users/123)
    • This closes a significant information disclosure vulnerability

Version 2.0.5

  • Enhancement: Added "Current Status" display to Core Protections tab
  • Shows which protections are ACTIVE (green) or Inactive (gray) in real-time
  • Helps verify settings are properly saved and active

Version 2.0.4

  • CRITICAL BUG FIX: Fixed root cause of URL scanning failure
    • WordPress Settings API sanitize callback was rejecting AJAX updates
    • Implemented _ajax_bypass marker to allow AJAX operations to update database
    • All AJAX handlers now properly save data without being blocked by sanitization
    • URLs now persist correctly in the database
    • Scanning now works as expected
  • Note: This was a fundamental architecture issue where WordPress's update_option() would return false when the sanitize callback returned unchanged data

Version 2.0.3

  • Bug Fix: Added protection against sanitize_options being called without active_tab marker
  • Enhancement: Added comprehensive server-side logging for debugging URL save/scan issues
  • Enhancement: Improved client-side console logging for better troubleshooting
  • Enhancement: Better error messages that show debug information in console

Version 2.0.2

  • Bug Fix: Fixed URL scanning issue where scanned URLs weren't being properly saved or retrieved
  • Enhancement: Improved AJAX handlers to ensure CSP Builder data structure is properly initialized
  • Enhancement: Added better error messages and debugging information for scan failures
  • Enhancement: Improved UI feedback when adding URLs (shows "Adding..." and "Added!" messages)
  • Enhancement: Better error handling with console logging for troubleshooting

Version 2.0.1

  • New Feature: CSP (Content Security Policy) Builder
    • Visual interface to scan pages and discover resources
    • No-code CSP generation with checkbox selection
    • Automatic nonce generation for inline scripts and styles
    • Report-Only mode for safe testing
    • Real-time policy preview and copy-to-clipboard
  • Bug Fix: Resolved settings persistence issue where saving one tab could overwrite settings from other tabs
  • Enhancement: Added tab-specific form handling to ensure all settings are preserved correctly

Version 1.1.0

  • Initial release with core protections and security headers

License

GPL-2.0-or-later. See the plugin header for license details.