WordPress powers more than 40% of the web, making it the most targeted CMS on the internet. This checklist is for developers, technical managers, and site owners who want a concrete, actionable plan to harden their WordPress installation against the most common threats — from brute-force attacks and plugin vulnerabilities to data leakage and malware injection. Work through each step in order, and you will have a significantly stronger security posture by the end.
Update WordPress Core, Themes, and Plugins
The majority of successful WordPress compromises exploit known vulnerabilities in outdated software. Attackers actively scan for sites running old versions and exploit published CVEs within hours of disclosure. Keeping everything current is your single highest-impact action.
- Navigate to Dashboard → Updates and apply all pending WordPress core updates immediately.
- Update every installed plugin — including inactive ones — to its latest stable release.
- Update every installed theme — including inactive ones — to its latest stable release.
- Enable automatic background updates for minor core releases by adding
define('WP_AUTO_UPDATE_CORE', 'minor');towp-config.php. - Subscribe to the WordPress Security Advisories feed or use a vulnerability database (e.g., WPScan Vulnerability Database) to stay informed about newly disclosed plugin and theme CVEs.
- Delete, rather than merely deactivate, any plugins or themes you no longer use — inactive code can still be exploited.
Harden Authentication and User Access
Weak credentials and unrestricted login endpoints are the top entry points for attackers. Hardening authentication dramatically reduces the risk of unauthorised access even if a password is compromised.
- Enforce a strong password policy for all user accounts — minimum 16 characters, mixing upper/lowercase, numbers, and symbols.
- Install and configure a two-factor authentication (2FA) plugin (e.g., WP 2FA, Wordfence Login Security) for all accounts with Editor role or higher.
- Install a login-limiting plugin to block IP addresses after a configurable number of failed login attempts (e.g., 5 attempts, 30-minute lockout).
- Change the default admin username from
adminto something non-guessable — create a new admin user, transfer content, and delete the originaladminaccount. - Disable XML-RPC if you do not use it (remote publishing, Jetpack, etc.) by adding
add_filter('xmlrpc_enabled', '__return_false');to your theme'sfunctions.phpor via a dedicated plugin. Sensagraph checks whether XML-RPC is publicly accessible on your site. - Restrict the
/wp-login.phpURL by IP allowlist using your server configuration or a plugin, or move it to a custom URL. - Review all user accounts and remove any that are no longer needed; ensure no account has more privileges than its role requires.
Secure wp-config.php and File Permissions
wp-config.php contains your database credentials, secret keys, and other sensitive configuration. Incorrect file permissions are a common vector for attackers to read or modify critical files.
- Set
wp-config.phppermissions to400(owner read-only) or at most440. - Move
wp-config.phpone directory above the WordPress root if your hosting environment allows it — WordPress will find it automatically. - Block direct HTTP access to
wp-config.phpat the web server level (Apache: add a<Files wp-config.php> deny from all </Files>block in.htaccess; Nginx: add alocation ~ /wp-config.php { deny all; }block). - Set WordPress directory permissions to
755and file permissions to644as a baseline; never use777on any file or directory. - Set
.htaccesspermissions to444(read-only). - Disable file editing via the WordPress admin by adding
define('DISALLOW_FILE_EDIT', true);towp-config.php. - Disable file modification (plugin/theme installation from admin) in high-security environments by adding
define('DISALLOW_FILE_MODS', true);towp-config.php. - Generate fresh secret keys and salts using the official WordPress secret-key generator and update them in
wp-config.php.
Enforce HTTPS and Strong TLS Configuration
Transmitting data over plain HTTP exposes credentials, session cookies, and user data to interception. A correctly configured TLS setup is now a baseline expectation — not an optional extra.
- Obtain and install a valid TLS certificate from a trusted CA (Let's Encrypt provides free certificates).
- Force HTTPS sitewide by updating WordPress settings: set both WordPress Address and Site Address to
https://in Settings → General. - Add a permanent HTTP-to-HTTPS redirect (301) at the server level — not just via WordPress.
- Disable TLS 1.0 and TLS 1.1; accept only TLS 1.2 and TLS 1.3 on your server.
- Use strong cipher suites — follow the Mozilla SSL Configuration Generator for your server software.
- Verify your certificate covers all subdomains you serve (wildcard or SANs as appropriate).
- Set a certificate expiry reminder at least 30 days before expiry; use auto-renewal (e.g., Certbot cron job). Sensagraph monitors TLS certificate validity and expiry on your site.
- Enable HTTP Strict Transport Security (HSTS) — see Step 05 for header configuration.
Configure HTTP Security Headers
Security headers instruct browsers to enforce policies that protect your visitors against cross-site scripting, clickjacking, MIME sniffing, and other client-side attacks. They take minutes to add and provide immediate protection.
- Add
Strict-Transport-Security: max-age=31536000; includeSubDomains; preloadto enforce HTTPS for one year across all subdomains. - Add
X-Frame-Options: SAMEORIGIN(or use the CSPframe-ancestorsdirective) to prevent clickjacking. - Add
X-Content-Type-Options: nosniffto prevent MIME-type sniffing attacks. - Add
Referrer-Policy: strict-origin-when-cross-originto control how much referrer information is shared. - Add
Permissions-Policyto disable browser features your site does not use (e.g., camera, microphone, geolocation). - Define a
Content-Security-Policy(CSP) header that whitelists only the origins from which your site loads scripts, styles, fonts, and media. Start in report-only mode (Content-Security-Policy-Report-Only) before enforcing. - Remove or obscure the
X-Powered-ByandServerheaders to reduce information disclosure. Sensagraph automatically checks all major security headers on your site and flags any that are missing or misconfigured.
Reduce Attack Surface — Plugins, Themes, and Features
Every additional plugin, theme, or enabled feature is a potential entry point. Minimising your installation's footprint directly reduces the number of vulnerabilities an attacker can target.
- Audit all installed plugins: remove any that are unused, abandoned (no updates in 12+ months), or have known unpatched vulnerabilities.
- Prefer plugins with large, active user bases and regular update histories — check the WordPress.org plugin page for last-updated date and active installs.
- Remove all themes except your active theme and its parent theme (if using a child theme).
- Disable the WordPress REST API user enumeration endpoint if you do not need it — add logic to return a 401 for unauthenticated
/wp-json/wp/v2/usersrequests. - Disable directory browsing on your web server (Apache: ensure
Options -Indexesis set; Nginx: ensureautoindex off;is set). - Disable pingbacks and trackbacks if not needed: go to Settings → Discussion and uncheck Allow link notifications from other blogs.
- Hide the WordPress version number — remove it from the
<head>by addingremove_action('wp_head', 'wp_generator');tofunctions.php. Sensagraph detects exposed version information and other fingerprinting vectors on your site.
Harden the WordPress Database
The database stores all site content, user credentials (hashed), and configuration. A misconfigured or easily guessable database setup provides attackers with a high-value target.
- Change the default WordPress table prefix from
wp_to a random string (e.g.,xk7q_) — do this at installation time or carefully using a dedicated plugin/manual process on existing sites. - Create a dedicated MySQL/MariaDB user for WordPress with only the privileges it needs:
SELECT,INSERT,UPDATE,DELETE,CREATE,ALTER,INDEX,DROPon the WordPress database only — notGRANT,FILE, or global privileges. - Use a strong, randomly generated database password (32+ characters).
- Ensure the database server is bound to
127.0.0.1(localhost only) and is not accessible from the public internet. - Disable remote root login on your database server.
- Schedule regular automated database backups and verify restoration procedures periodically.
Deploy a Web Application Firewall (WAF)
A WAF inspects incoming HTTP requests and blocks known malicious patterns — SQL injection, XSS attempts, and vulnerability scanners — before they reach WordPress. This adds a critical layer between the internet and your application.
- Choose between a plugin-based WAF (e.g., Wordfence, Sucuri) or a network/DNS-level WAF (e.g., Cloudflare, AWS WAF). A network-level WAF provides protection even if WordPress itself is compromised.
- Enable OWASP Core Rule Set (CRS) rules if using a configurable WAF such as ModSecurity or Cloudflare WAF.
- Enable bot protection and rate limiting on your WAF to slow brute-force and scraping attempts.
- Configure the WAF to block or challenge requests that attempt to access sensitive paths such as
/wp-config.php,/.env, and/xmlrpc.php. - Review WAF logs weekly for blocked attack patterns and tune rules to reduce false positives without opening gaps.
- Test WAF effectiveness after initial setup using a safe simulated attack (e.g., send a request with
?test=<script>alert(1)</script>and confirm it is blocked).
Back Up Regularly and Test Restores
No security posture is perfect. Reliable, tested backups are your last line of defence — they let you recover quickly from ransomware, accidental deletion, or a successful attack without paying a ransom or losing data.
- Back up both the database and all WordPress files (core, plugins, themes, uploads) on a scheduled basis — at least daily for active sites.
- Store backups in at least two locations: one offsite (e.g., S3, Google Cloud Storage, Backblaze) and one local or staging environment.
- Encrypt backup archives before storing them offsite.
- Test your restore process at least quarterly — a backup you have never restored is an untested assumption.
- Retain multiple backup generations (e.g., 7 daily, 4 weekly, 3 monthly) so you can roll back to a point before a compromise that was not immediately detected.
- Document your restoration runbook and keep it accessible outside your WordPress environment.
Monitor and Scan Continuously
Security is not a one-time task. New vulnerabilities are disclosed daily, configurations drift over time, and attackers continuously probe for weaknesses. Continuous monitoring catches issues before they become incidents.
- Set up server-level logging for PHP errors, Apache/Nginx access logs, and WordPress debug logs; review them regularly or pipe them to a log management tool.
- Enable WordPress activity logging with a plugin (e.g., WP Activity Log) to record user logins, content changes, plugin activations, and settings modifications.
- Configure uptime monitoring — get alerted within minutes if your site goes down, which can be an early indicator of an attack or defacement.
- Perform regular file integrity checks to detect unauthorised changes to core WordPress files, plugins, or themes.
- Check your domain against known malware and phishing blocklists (Google Safe Browsing, Sucuri SiteCheck) at least monthly.
- Run automated external security scans to detect exposed sensitive files, missing headers, TLS issues, and known vulnerabilities — Sensagraph continuously scans your WordPress site and alerts you to new security issues as they arise.
- Assign a clear owner responsible for reviewing security alerts and acting on them within a defined SLA (e.g., critical issues within 24 hours, high within 72 hours).