A WordPress Security Hardening Checklist That Actually Matters
Most "WordPress security checklists" are padded with plugin recommendations and vague advice to "use strong passwords." This one is the actual list I worked through on a live WooCommerce and LearnDash platform handling real payments — in order, with the one rollout mistake that will break your checkout if you skip a step.
Close user enumeration first
By default, /wp-json/wp/v2/users hands out usernames to anyone who asks — and so does ?author=1. Both are trivial to script against. This is step one because it's the cheapest attack to block and the one most sites never touch.
Stop advertising your version numbers
Generator tags in your HTML broadcast your exact WordPress and plugin versions to anyone who views source — including on the login page, which most "hardening" guides skip entirely. If a vulnerability drops for a plugin version you're running, you've just told every scanner on the internet that you're a target. Strip these sitewide, login included, and remove the X-Powered-By header while you're at it — it does the same thing for your PHP version.
The five headers most sites are missing
In a recent crawl of a client site (74 pages, 410 URLs), every single URL was missing the same five security headers. That's not a one-off — it's the WordPress default:
- HSTS — forces HTTPS, no exceptions
- X-Content-Type-Options: nosniff — stops browsers guessing content types in ways attackers can exploit
- X-Frame-Options — blocks clickjacking via iframes
- Referrer-Policy (strict-origin-when-cross-origin) — stops URLs leaking on downgrade
- Content-Security-Policy — the big one, and the one that will break your site if you rush it
The CSP mistake that breaks Stripe
Content-Security-Policy is the header that actually stops injected scripts from running. It's also the one most likely to silently break your checkout, your embedded video, or a plugin's admin screen if you flip it straight to enforcement. Deploy it in Report-Only mode first. You'll get a stream of violation reports showing exactly what the policy would have blocked — Stripe.js, Google Fonts, your LMS video provider — and you can allow-list those specific sources before switching to full enforcement. Skipping this step is how "we hardened security" turns into "why is checkout broken."
Close XML-RPC, unless you specifically need it
XML-RPC is a legacy protocol still enabled by default, and it's a favorite brute-force and amplification vector. Unless you're actively using the Jetpack mobile app or a specific integration that requires it, disable it entirely.
Account-level hardening
Two-factor authentication and login-attempt limiting on every account with publish or admin access — not just the main admin account. Rename or reassign the default "admin" username if it's still in use. Remove readme.html and license.txt, which quietly confirm your exact WordPress version to anyone who checks.
If you're on WooCommerce: check HPOS compatibility now
WooCommerce's High-Performance Order Storage (HPOS) changes how order data is stored. Any custom code touching orders directly — instead of through WooCommerce's CRUD functions — needs to be HPOS-compatible before you enable it, not after something breaks in production.
Do this before you call it done
Every item above was applied to a live e-commerce and course platform without downtime, by sequencing correctly: read-only checks first, header rollout in monitoring mode before enforcement, account hardening throughout. Security work that breaks checkout on day one teaches the client to distrust the next update — sequencing is not optional.
Running WordPress or WooCommerce and not sure where you stand? I review platform security as part of a Platform Review — book a free 30-minute call.
Let’s find out what’s holding your site back
Book a free 30-minute call — in English, German, or Arabic — and get at least three concrete improvements, whether we work together or not.
Book your free call