
WordPress security checklist: what to check before and after going live
A practical WordPress security checklist: what to lock down before you publish (updates, login, permissions, headers, backups) and what to monitor after launch.
WordPress powers a large share of the web, which makes it the default target for automated attacks. Bots don’t care whether your site is important: they scan every new domain for known vulnerable plugins, weak logins and exposed files, usually within hours of it going online. Most compromised WordPress sites weren’t targeted; they were simply unpatched or misconfigured.
Here’s what to do before you publish, and what to keep doing after.
Before going live
1. Start from a clean, minimal install
- Install WordPress from wordpress.org, never from a “nulled” (pirated) theme or plugin bundle: they are the number one source of backdoors.
- Delete what you don’t use: default plugins (Hello Dolly), unused themes (keep one default theme as fallback), sample content.
- Every plugin is attack surface. Fewer, well-maintained plugins beat many. Check that each one has recent updates, a decent install base and no open unpatched vulnerability reports.
2. Keep everything updated
Most WordPress compromises come from plugins and themes, not from core. Enable automatic updates for minor core releases (on by default) and for plugins you trust. Also check the PHP version: unsupported PHP versions no longer receive security fixes.
3. Lock down authentication
- Don’t use
adminas username and use a unique, long password from a password manager. - Enable two-factor authentication for every administrator and editor. To see why passkeys are a stronger option, read WebAuthn and passkeys.
- Limit login attempts and consider changing or protecting
/wp-login.php. - Give each person their own account with the least privilege they need (Editor, not Administrator).
- Disable the built-in file editor in
wp-config.php, so a stolen admin session can’t write PHP from the dashboard:
define( 'DISALLOW_FILE_EDIT', true );
4. Harden wp-config.php and file permissions
// Force admin and login over HTTPS
define( 'FORCE_SSL_ADMIN', true );
// Never show errors to visitors
define( 'WP_DEBUG', false );
define( 'WP_DEBUG_DISPLAY', false );
- Use unique authentication keys and salts (generate them from the official API).
- Move
wp-config.phpabove the web root if your host allows it, or block direct access. - Typical permissions: directories
755, files644,wp-config.php600or640. The web server user should not own core files unless you need auto-updates through the dashboard. - Use a non-default database table prefix and a dedicated database user with only the privileges WordPress needs, not
root.
5. Force HTTPS and add security headers
Get a certificate (Let’s Encrypt is free), redirect HTTP to HTTPS, and enable HSTS once you’re sure everything works over HTTPS. Then add response headers at the web server level:
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
X-Frame-Options: SAMEORIGIN
Permissions-Policy: camera=(), microphone=(), geolocation=()
A Content Security Policy is the strongest header but the hardest on WordPress, because themes and plugins inject inline scripts. Start in report-only mode. See the CSP guide and the follow-up on nonces and strict-dynamic.
6. Reduce what the site reveals and exposes
- Block XML-RPC (
/xmlrpc.php) if you don’t use it. It allows brute-force amplification viasystem.multicall. - Disable directory listing.
- Block PHP execution in
wp-content/uploads/, where an uploaded webshell would land. - Make sure backups,
.git,.env,*.sql,*.zipanddebug.logare not reachable from the web: search engines and bots look for them. - Review the REST API user endpoint (
/wp-json/wp/v2/users): it can leak usernames. Restrict it if you don’t need it public.
7. Set up backups you have actually restored
A backup you never tested is a hope, not a backup. Keep files + database, stored off the server, with more than one retention point (so ransomware or a silent compromise doesn’t overwrite the only good copy). Do one test restore before launch.
8. Add a firewall layer
A web application firewall (Cloudflare, Sucuri, or a plugin such as Wordfence) blocks known-bad requests, rate-limits login attempts and hides your origin IP. It doesn’t replace updates, but it buys time between a vulnerability disclosure and your patch.
Pre-launch checklist
- WordPress core, all plugins, themes and PHP up to date
- Unused plugins/themes deleted, nothing “nulled”
- No
adminuser, strong unique passwords, 2FA for privileged users - Login attempts limited
-
DISALLOW_FILE_EDITset,WP_DEBUG_DISPLAYoff - Unique salts, restrictive file permissions, limited DB user
- HTTPS forced, valid certificate, security headers set
- XML-RPC blocked if unused, directory listing off, PHP blocked in uploads
- No sensitive files reachable (
.env,.git, dumps,debug.log) - Off-server backup made and restore tested
- Firewall / WAF active
- Search engines blocked on staging (
Discourage search engines) and re-enabled on production
After going live
Security is a routine, not a launch task.
1. Verify from the outside
Scan the live site: check the headers with securityheaders.com, TLS with SSL Labs, and try requesting /xmlrpc.php, /.git/config, /wp-content/debug.log and /wp-content/uploads/ yourself. Anything other than 403/404 needs a look.
2. Monitor updates and vulnerabilities
Subscribe to a vulnerability feed for WordPress plugins (Patchstack, WPScan/Wordfence intelligence). A plugin can be safe on Monday and have a critical exploit on Friday. Check the update list at least weekly, and apply security updates quickly, testing on staging first for big ones.
3. Log and alert
- Keep an activity log (who logged in, who changed what, plugins installed).
- Get alerts on new admin users, changed core files, and failed-login spikes.
- Use file integrity checks:
wp core verify-checksumsandwp plugin verify-checksums --all(WP-CLI) compare files against the official releases.
wp core verify-checksums
wp plugin verify-checksums --all
4. Uptime and malware monitoring
Uptime monitoring catches defacement or downtime. A periodic malware scan (server-side, since plugin scanners can be evaded by the malware itself) catches injected code. Also watch Google Search Console’s Security issues report: Google often flags a hacked site before you notice.
5. Test your backups again
Restore to a staging copy every few months. Confirm the schedule still runs and the storage isn’t full.
6. Review users and plugins periodically
Remove accounts of people who left, rotate API keys, and drop plugins you stopped using. Every removed plugin is one less thing to patch.
7. Have an incident plan
If the site is compromised: put it in maintenance mode, restore from a clean backup (don’t just “clean” files by hand), change all passwords (WordPress, database, hosting, FTP/SSH) and salts, update everything, then find how they got in, or it will happen again.
Post-launch routine
- Weekly: apply updates, check the security/activity log
- Monthly: review users and plugins, check Search Console security issues
- Quarterly: test a backup restore, re-run header and TLS scans
- Always: an alert channel that a human actually reads
Running WordPress in containers
If you deploy with Docker, you get useful isolation (read-only filesystem, no shell tooling in the image, secrets via environment). It doesn’t remove the need for any of the above, since the vulnerable code is still inside the container. See WPDockerize for a quick stack.
Conclusion
Most WordPress incidents come from a short list of causes: outdated plugins, weak or reused passwords, exposed files and missing backups. The checklist above targets exactly those. Do it once properly before launch, then keep a small, boring routine going.
References:

Co-Founder & CTO at PAPION. Senior full-stack engineer specializing in React, TypeScript, Node.js, and application security.