Under attack? Get incident response help

info@angelforce.eu
WordPress

A practical WordPress security checklist

Twelve WordPress hardening steps in a sensible order, from updates and abandoned plugins to 2FA, XML-RPC, backups, file integrity and a WAF.

Also in:TürkçeDeutschFrançaisEspañolItalianoPolskiNederlandsEesti

Illustration: A practical WordPress security checklist

A WordPress site is only as strong as its weakest plugin, account or backup. Core WordPress receives regular security releases; what you add to it and how you run it are up to you. This checklist covers the controls that matter most, roughly in the order we would apply them.

1. Keep core, plugins and themes updated

Automatic background updates for core have existed since WordPress 3.7, and by default they cover minor releases. Since WordPress 5.5, you can also switch on automatic updates for each plugin and theme from the admin screens.

  • Turn on auto-updates for plugins from reputable developers, and review the rest weekly.
  • Auto-updates rely on WP-Cron. Check Tools > Site Health for errors, because a broken cron means updates silently stop.
  • Make sure you can roll back before you rely on automatic updates. The WordPress documentation recommends the same.

2. Remove abandoned and unused plugins

The WordPress hardening guide is direct: keep plugins updated and delete the ones you do not use. Deactivating is not enough, because the code stays on the server.

The WordPress.org plugin directory gives you two warning signs:

  • A yellow notice saying a plugin "hasn't been tested with the latest 3 major releases of WordPress".
  • A red notice saying a plugin has been closed and is no longer available for download. After 60 days, the reason is shown, and "security issue" is one of the listed reasons.

A closed plugin will not receive updates through WordPress.org. Replace it. Never install "nulled" copies of premium plugins, and only install from WordPress.org or vendors you trust.

3. Audit administrator accounts

List every account with the Administrator role and remove the ones nobody can explain. With WP-CLI:

wp user list --role=administrator --fields=ID,user_login,user_email,user_registered

Give each person their own named account, never a shared admin login. Use the lowest role that does the job: most content editors do not need Administrator. Require strong, unique passwords, ideally stored in a password manager.

4. Enable two-factor authentication

Turn on 2FA for every administrator. WordPress core does not include 2FA, so you need a plugin or a single sign-on provider that enforces it. Prefer methods such as security keys or passkeys where your plugin supports them, and keep recovery codes somewhere safe.

5. Rate-limit logins and decide on XML-RPC

The WordPress documentation describes wp-login.php and xmlrpc.php as common brute-force targets. It recommends rate-limiting login attempts at the edge (a WAF or CDN) or at the web server. A security plugin can throttle logins too, but it runs in PHP, so the server-level option holds up better under heavy traffic.

If you do not use XML-RPC, disable it. Some mobile apps and services such as Jetpack need it, so check first. Note that the xmlrpc_enabled filter only disables methods that need authentication. Pingbacks and other unauthenticated methods keep working. To switch it off fully, block the file at the web server. For nginx:

location = /xmlrpc.php {
    deny all;
}

6. Turn off the built-in file editor

The dashboard's theme and plugin editor lets anyone with an administrator session change PHP code. Disable it in wp-config.php:

define( 'DISALLOW_FILE_EDIT', true );

According to the wp-config.php documentation, DISALLOW_FILE_MODS goes further and also blocks plugin and theme installs and updates from the dashboard. Use it only if you deploy changes another way, such as through Git or WP-CLI.

7. Keep backups off the server and outside the web root

The hardening guide recommends regular backups of both files and database, several snapshots, and a trusted storage location. Protect their integrity with encryption, recorded hashes or read-only media.

Two practical rules follow. A backup inside the web root, such as a zip file in wp-content, can be downloaded by anyone who guesses its name. A backup on the same server can be deleted by the same attacker. Keep at least one copy somewhere the site's credentials cannot reach, and test a full restore.

8. Check file integrity

WP-CLI can compare your files with the official WordPress.org checksums without loading WordPress:

wp core verify-checksums --include-root
wp plugin verify-checksums --all

The first command flags modified core files, and --include-root warns about unexpected files in the root directory. The second compares plugins against WordPress.org checksums, so it only helps for plugins hosted there. Also look for PHP files in wp-content/uploads, which should normally contain only media.

9. Use a least-privilege database user

Give each site its own database and its own database user, with rights on that database only. Never connect as the database root user.

The hardening guide notes that day-to-day operation needs only SELECT, INSERT, UPDATE and DELETE. It does not recommend revoking DROP, ALTER and GRANT, because plugins and major updates may need to change the schema. If you remove them anyway, keep tested backups.

10. Set file permissions

The guide's starting point is 755 for directories and 644 for files. Core files, wp-admin and wp-includes should be writable only by your user account, not by the web server. wp-content is the exception: the web server needs to write there for uploads. For wp-config.php, the guide suggests 400 or 440.

find /var/www/example -type d -exec chmod 755 {} \;
find /var/www/example -type f -exec chmod 644 {} \;
chmod 440 /var/www/example/wp-config.php

Adjust the paths and ownership to your hosting setup before running these commands.

11. Send security headers

Headers such as Strict-Transport-Security, Content-Security-Policy, X-Content-Type-Options and Referrer-Policy add browser-side protection. Set them at the web server or CDN rather than through a plugin where you can. Start with a report-only Content Security Policy, because themes and page builders may rely on inline scripts.

12. Put a WAF in front

The WordPress documentation describes three levels: security plugins that filter requests inside WordPress, a server-level firewall such as ModSecurity, and reverse-proxy services that filter traffic before it reaches your server. The further out the filtering happens, the less load reaches PHP. A WAF does not replace updates. It buys time between a disclosure and your patch.

The short version

AreaMinimum
UpdatesCore minor auto-updates on, plugins reviewed weekly
PluginsNo closed, abandoned or unused plugins installed
AccountsNamed accounts, few administrators, 2FA for all of them
LoginRate limiting at server or edge, XML-RPC blocked if unused
Code changesDISALLOW_FILE_EDIT set
BackupsOff-server, outside web root, restore tested
IntegrityChecksums verified, no PHP in uploads
DatabaseOne user per site, rights on its own database only
BrowserHSTS and a tested CSP
PerimeterWAF or reverse proxy in front

Where to start

Start with the first four items. They take little time and need no change to your hosting. Then check your current headers with our security headers checker.

If you want this checked for you, SecAudit scans WordPress for malware and web shells, verifies file integrity against official checksums and maps installed plugins to known vulnerabilities.

How we can help

SecAudit

Our own product. SecAudit scans WordPress sites for malware, vulnerable code, changed files and known vulnerabilities, and turns the results into reports mapped to OWASP, GDPR and NIS2.

Security headers scanner

Grade a website’s HTTP security headers, cookies and TLS certificate, with a fix for every finding.

Contact us
AngelForce team

Written by the AngelForce team: security consultants with CEH, LPT Master and CISA certifications who test, monitor and defend systems for organisations across Europe and Türkiye.

Written with AI assistance from public sources listed below, and reviewed by the AngelForce team before publication.

Sources

  1. developer.wordpress.org/advanced-administration/security/hardening/
  2. developer.wordpress.org/advanced-administration/security/brute-force/
  3. developer.wordpress.org/plugins/wordpress-org/alerts-and-warnings/
  4. developer.wordpress.org/reference/hooks/xmlrpc_enabled/
  5. developer.wordpress.org/cli/commands/core/verify-checksums/
  6. wordpress.org/documentation/article/plugins-themes-auto-updates/

Articles about WordPress

Tell us what you need to protect

Describe your environment and what you want to achieve. We will reply by email.

Contact us
info@angelforce.eu

AngelForce OÜ · Tallinn, Estonia