WordPress Security Hardening: 10 Configuration Fixes to Do This Week
Why WordPress Sites Get Compromised
WordPress powers about 43% of the web, which makes it the most targeted CMS by a wide margin. But most successful WordPress attacks don't exploit sophisticated zero-days — they exploit predictable configurations that most site owners never change.
The fixes below require no plugins and take most developers under an hour to implement. None of them are optional.
1. Remove the WordPress Version from Your HTML
By default, WordPress announces its version number in your page's <head>:
<meta name="generator" content="WordPress 6.9.4" />
This is a free fingerprint for automated scanners. They use it to look up which known vulnerabilities affect that exact version. Remove it in your theme's functions.php:
remove_action('wp_head', 'wp_generator');
Also remove it from the RSS feed:
add_filter('the_generator', '__return_empty_string');
2. Hide the WordPress Version from REST API Responses
The version is also exposed in REST API responses at /wp-json/. Remove it:
add_filter('rest_authentication_errors', function($result) {
return $result;
});
add_filter('json_index', function($response) {
$data = $response->get_data();
unset($data['namespaces']);
$response->set_data($data);
return $response;
});
Or simply redirect /wp-json/ for unauthenticated requests in your server config if you don't use the REST API publicly.
3. Add Security Headers via wp-config or Server Config
WordPress doesn't set security headers by default. The right place to add them is your server config (Nginx or Apache), not functions.php — PHP headers fire too late for some browsers.
# Nginx
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
For Content-Security-Policy, test carefully — WordPress loads a lot of inline scripts in the admin. Use Content-Security-Policy-Report-Only first to identify what needs to be whitelisted before enforcing.
4. Protect wp-login.php
The WordPress login page receives constant automated brute-force attempts. Rate-limit or restrict it at the server level:
# Nginx — limit login attempts
location = /wp-login.php {
limit_req zone=one burst=5 nodelay;
fastcgi_pass ...;
}
Or restrict access to specific IPs if your team works from fixed locations:
location = /wp-login.php {
allow 192.0.2.1; # your IP
deny all;
}
If you can't restrict by IP, at minimum install a plugin like WP Limit Login Attempts or enable two-factor authentication.
5. Disable XML-RPC If You Don't Use It
XML-RPC is a legacy remote publishing interface that's rarely used today but frequently abused for brute-force attacks and DDoS amplification. Disable it entirely:
# Nginx
location = /xmlrpc.php {
deny all;
return 403;
}
Or in functions.php:
add_filter('xmlrpc_enabled', '__return_false');
6. Block Direct Access to wp-config.php and .htaccess
These files should never be directly accessible from the web. In Nginx they're blocked by default (PHP-FPM won't serve them), but in Apache add this to your .htaccess:
<Files wp-config.php>
Order allow,deny
Deny from all
</Files>
7. Disable File Editing from the Dashboard
The WordPress theme and plugin file editors in the admin panel are a significant risk — if an admin account is compromised, attackers can inject malicious PHP directly without needing server access. Disable them in wp-config.php:
define('DISALLOW_FILE_EDIT', true);
This has no impact on legitimate usage and eliminates an entire attack vector.
8. Keep Plugins and Themes Updated — and Audit Them
Outdated plugins are the #1 cause of WordPress compromises, not weak passwords or brute force. The fix isn't glamorous: keep everything updated, and remove plugins you're not actively using. Every inactive plugin is an attack surface.
Run a quick audit: go to Plugins → Installed Plugins, filter by inactive, and delete everything that isn't needed. Then repeat for themes — delete every theme except the active one and one parent theme as a fallback.
9. Configure Proper Cookie Security
WordPress sets several session cookies. Make sure they're sent over HTTPS only and inaccessible to JavaScript by adding to wp-config.php:
@ini_set('session.cookie_secure', true);
@ini_set('session.cookie_httponly', true);
@ini_set('session.cookie_samesite', 'Lax');
You should also force SSL for admin sessions and logins:
define('FORCE_SSL_ADMIN', true);
10. Set Up DMARC for Your Domain
This one isn't WordPress-specific, but it matters for any WordPress site with a contact form or transactional email. If your domain doesn't have a DMARC record — or has one set to p=none — anyone can send email spoofing your domain. Visitors who receive a phishing email "from" your domain will lose trust in your site.
See our complete DMARC setup guide for the exact records to add.
Verify Your Configuration
After making these changes, run a WebSentry audit to confirm your security headers, cookie flags, and DNS records are all configured correctly. The scanner checks the items above automatically and flags anything that still needs attention.
A hardened WordPress site should score B or higher on a WebSentry audit. If you're still below that after these fixes, the report will show exactly which issues remain.
Check Your Website's Security
Run a free security scan and get your A-F grade in seconds.
Scan Your Site Free