Diego Betto
Photo by Jakub Żerdzicki on Unsplash

Diego Betto · September 21, 2026 · 6 min di lettura

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.

Condividi:XLinkedInFacebookWhatsApp

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 admin as 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.php above the web root if your host allows it, or block direct access.
  • Typical permissions: directories 755, files 644, wp-config.php 600 or 640. 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 via system.multicall.
  • Disable directory listing.
  • Block PHP execution in wp-content/uploads/, where an uploaded webshell would land.
  • Make sure backups, .git, .env, *.sql, *.zip and debug.log are 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 admin user, strong unique passwords, 2FA for privileged users
  • Login attempts limited
  • DISALLOW_FILE_EDIT set, WP_DEBUG_DISPLAY off
  • 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-checksums and wp 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:

Condividi:XLinkedInFacebookWhatsApp
Diego Betto

Written by

Diego Betto

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