Essential Security Headers for WordPress Sites
Learn how to implement essential HTTP security headers for WordPress. Protect against XSS, clickjacking, and other browser-based attacks.
HTTP security headers instruct browsers how to handle your site's content, providing crucial protection against common web attacks. Properly configured headers significantly enhance WordPress security with minimal performance impact.
Understanding Security Headers
Security headers are HTTP response headers that control browser behavior. They provide defense-in-depth by preventing certain attack types even if other vulnerabilities exist.
Content Security Policy (CSP)
CSP prevents XSS attacks by controlling which resources can load:
Basic CSP Configuration
// Add Content Security Policy header
add_action('send_headers', function() {
$csp = "default-src 'self'; ";
$csp .= "script-src 'self' 'unsafe-inline' https://www.google.com https://www.gstatic.com; ";
$csp .= "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; ";
$csp .= "img-src 'self' data: https:; ";
$csp .= "font-src 'self' https://fonts.gstatic.com; ";
$csp .= "frame-src https://www.google.com; ";
$csp .= "connect-src 'self';";
header("Content-Security-Policy: " . $csp);
});
CSP Directives Explained
- default-src - Fallback for unspecified directives
- script-src - Valid JavaScript sources
- style-src - Valid stylesheet sources
- img-src - Valid image sources
- font-src - Valid font sources
- connect-src - Valid AJAX/WebSocket targets
- frame-src - Valid iframe sources
X-Frame-Options
Prevents clickjacking by controlling iframe embedding:
// Prevent site from being framed
add_action('send_headers', function() {
header('X-Frame-Options: SAMEORIGIN');
});
// Or deny all framing
header('X-Frame-Options: DENY');
X-Content-Type-Options
Prevents MIME type sniffing attacks:
add_action('send_headers', function() {
header('X-Content-Type-Options: nosniff');
});
X-XSS-Protection
Enables browser XSS filtering:
add_action('send_headers', function() {
header('X-XSS-Protection: 1; mode=block');
});
Note: Modern browsers deprecate this in favor of CSP, but it provides backup for older browsers.
Strict-Transport-Security (HSTS)
Forces HTTPS connections:
add_action('send_headers', function() {
if (is_ssl()) {
header('Strict-Transport-Security: max-age=31536000; includeSubDomains; preload');
}
});
HSTS Parameters
- max-age - How long to enforce HTTPS (seconds)
- includeSubDomains - Apply to all subdomains
- preload - Include in browser preload lists
Referrer-Policy
Controls referrer information sent with requests:
add_action('send_headers', function() {
header('Referrer-Policy: strict-origin-when-cross-origin');
});
Referrer Policy Options
- no-referrer - Never send referrer
- same-origin - Send only for same-origin requests
- strict-origin - Send origin only, downgrade on HTTPS to HTTP
- strict-origin-when-cross-origin - Full URL same-origin, origin cross-origin
Permissions-Policy
Controls browser features:
add_action('send_headers', function() {
$policy = "geolocation=(), ";
$policy .= "microphone=(), ";
$policy .= "camera=(), ";
$policy .= "payment=(), ";
$policy .= "usb=()";
header("Permissions-Policy: " . $policy);
});
Complete Header Implementation
// Comprehensive security headers
add_action('send_headers', function() {
// Prevent clickjacking
header('X-Frame-Options: SAMEORIGIN');
// Prevent MIME sniffing
header('X-Content-Type-Options: nosniff');
// XSS protection (legacy)
header('X-XSS-Protection: 1; mode=block');
// Referrer policy
header('Referrer-Policy: strict-origin-when-cross-origin');
// HSTS (only on HTTPS)
if (is_ssl()) {
header('Strict-Transport-Security: max-age=31536000; includeSubDomains');
}
// Permissions policy
header('Permissions-Policy: geolocation=(), microphone=(), camera=()');
// Content Security Policy
header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';");
});
.htaccess Configuration
Add headers via Apache configuration:
# Security Headers
<IfModule mod_headers.c>
Header set X-Frame-Options "SAMEORIGIN"
Header set X-Content-Type-Options "nosniff"
Header set X-XSS-Protection "1; mode=block"
Header set Referrer-Policy "strict-origin-when-cross-origin"
Header set Permissions-Policy "geolocation=(), microphone=(), camera=()"
</IfModule>
Testing Security Headers
Verify your headers are working:
- SecurityHeaders.com - Free online scanner
- Browser DevTools - Network tab shows headers
- curl command:
curl -I https://yoursite.com
Common Issues
- CSP breaking inline scripts - Use nonces or hashes
- Third-party services blocked - Add to appropriate directives
- Admin functionality affected - Exclude admin pages if needed
Conclusion
Security headers provide essential browser-level protection with minimal implementation effort. Start with basic headers and progressively tighten policies as you identify all required resources.
Written by Sarah Chen
WP Folder Shield Team