WordPress powers over 43% of the web, making it the single largest target for automated attacks. Every day, bots scan millions of WordPress installations looking for outdated plugins, weak credentials, and misconfigured permissions. The good news: most WordPress compromises are entirely preventable.
This checklist covers every layer of WordPress security, from the login page to the database, from file permissions to HTTP headers. Whether you manage one blog or a hundred client sites, work through each section systematically. Use our WordPress Security Scanner to verify your progress as you go.
Before hardening anything, you need to understand what attackers actually target. A typical WordPress installation exposes dozens of entry points, and each one requires specific defenses.
WordPress compromises fall into a few well-documented categories, ranked by frequency:
wp-login.php and xmlrpc.php.wp-config.php, exposed .git directories, open directory listings, and missing security headers.Read more about real-world plugin exploitation in our article on how attackers exploit outdated WordPress plugins.
The WordPress login page is the most attacked endpoint on any WordPress site. Hardening it is step one.
This sounds obvious, but weak passwords remain the number one cause of brute-force success. Enforce these rules:
admin username and create a custom administrator account2FA makes stolen credentials useless. Use TOTP-based 2FA (Google Authenticator, Authy) rather than SMS, which is vulnerable to SIM-swapping. Apply 2FA to every account with edit_posts capability or higher.
Rate-limit login attempts to block brute-force bots. After 5 failed attempts, lock the IP for 30 minutes. Consider moving wp-login.php to a custom URL, though this is security-through-obscurity and should complement, not replace, real protections.
The xmlrpc.php endpoint allows authentication bypass via the system.multicall method, enabling attackers to test hundreds of passwords in a single HTTP request. Unless you rely on the WordPress mobile app or Jetpack, disable it entirely:
# In .htaccess
<Files xmlrpc.php>
Order Deny,Allow
Deny from all
</Files>Plugins are the Achilles heel of WordPress security. Every plugin you install is third-party code running with the same privileges as WordPress core.
Every active plugin increases your attack surface. Audit your plugin list ruthlessly:
Use our WordPress Security Scanner to identify plugins with known CVEs. For JavaScript-heavy themes and plugins, run a JavaScript vulnerability scan to catch dangerous frontend libraries. Our article on scanning WordPress for known vulnerabilities walks through the full process.
Enable auto-updates for minor WordPress core releases (enabled by default since WordPress 5.6). For plugins and themes, enable auto-updates selectively or use a staging workflow:
# In wp-config.php – enable auto-updates for plugins
add_filter( 'auto_update_plugin', '__return_true' );
# Or selectively via the dashboard:
# Dashboard → Plugins → Enable auto-updates per pluginIncorrect file permissions are a silent vulnerability. On a compromised shared host, loose permissions let other accounts on the same server read your database credentials.
# Directories: 755 (owner rwx, group rx, other rx)
find /var/www/html -type d -exec chmod 755 {} \;
# Files: 644 (owner rw, group r, other r)
find /var/www/html -type f -exec chmod 644 {} \;
# wp-config.php: 400 or 440 (owner read-only)
chmod 400 wp-config.php
# .htaccess: 444 (read-only for all)
chmod 444 .htaccessWordPress automatically checks one directory above the web root for wp-config.php. Moving it there prevents direct HTTP access even if your server is misconfigured:
# If WordPress is in /var/www/html
mv /var/www/html/wp-config.php /var/www/wp-config.phpThe built-in theme and plugin editor lets any admin account modify PHP files directly from the browser. If an admin account is compromised, this is an instant backdoor. Disable it:
# In wp-config.php
define( 'DISALLOW_FILE_EDIT', true );The WordPress database contains everything: credentials, content, session tokens, and configuration.
The default wp_ prefix makes SQL injection attacks trivially scriptable. Change it during installation. For existing sites, changing the prefix is possible but requires updating the $table_prefix variable in wp-config.php and renaming every table and its references in usermeta and options.
The MySQL user for WordPress should have only the privileges it actually needs:
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER
ON wordpress_db.*
TO 'wp_user'@'localhost';Notably, FILE, PROCESS, SUPER, and GRANT OPTION should never be granted to the WordPress database user.
WordPress uses secret keys and salts to secure cookies and session tokens. Generate fresh ones at https://api.wordpress.org/secret-key/1.1/salt/ and paste them into wp-config.php. Regenerate them if you suspect a compromise – this immediately invalidates all existing sessions.
The .htaccess file is your first line of defense on Apache servers. These rules block common attack patterns at the server level, before WordPress even loads.
# Protect wp-includes
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]
</IfModule>
# Prevent directory browsing
Options -Indexes
# Block access to sensitive files
<FilesMatch "(^\.ht|wp-config\.php|readme\.html|license\.txt)">
Order Allow,Deny
Deny from all
</FilesMatch>
# Disable server signature
ServerSignature OffAlso consider adding security headers through .htaccess or your server configuration. Headers like Content-Security-Policy, X-Frame-Options, and Strict-Transport-Security provide defense-in-depth against XSS, clickjacking, and protocol downgrade attacks. Test your headers with our Secure Headers Test tool.
A WAF inspects incoming HTTP requests and blocks malicious patterns before they reach WordPress. There are two categories:
Services like Cloudflare, Sucuri, and AWS WAF sit in front of your server as a reverse proxy. They filter traffic at the network edge, blocking attacks before they consume your server resources. Cloud WAFs also provide DDoS protection and CDN benefits.
Plugins like Wordfence and NinjaFirewall run as PHP code within WordPress. They offer WordPress-specific rulesets but consume server resources for every request. Read our comparison of WordPress security plugins versus manual hardening to understand the trade-offs.
../, file://, php://)wp-login.php and xmlrpc.phpSecurity is not a one-time configuration. You need continuous monitoring to detect compromises early.
Compare your WordPress core files, plugin files, and theme files against known-good checksums. WordPress provides a built-in integrity check via wp core verify-checksums in WP-CLI. For plugins, use our WordPress Security Scanner to check for known vulnerabilities and unexpected file modifications.
Schedule regular scans of your WordPress installation. At minimum, scan for:
crossdomain.xml and clientaccesspolicy.xml – see our article on cross-domain policy risksA sudden site outage or redirect to a malicious domain is often the first visible sign of compromise. Use a service like our Redirect Checker to verify your site loads correctly, and set up uptime alerts that notify you within minutes of downtime.
When a compromise is detected, speed matters. Prepare a documented plan in advance:
Every WordPress site must run on HTTPS. In 2026, there is no excuse for serving any page over plain HTTP. Ensure TLS is configured correctly:
wp-admin and wp-login.php: define( 'FORCE_SSL_ADMIN', true );Strict-Transport-Security header with a minimum max-age of 31536000 (one year)Use this condensed reference to verify every layer is addressed:
wp-config.php moved above web rootwp-config.php.htaccess hardened with directory protection and file blocksCSP, HSTS, X-Frame-Options)Run each of these checks against your site now. Start with our WordPress Security Scanner for an instant overview, then work through this checklist item by item.