Hardening a WordPress site you actually ship requires more than just plugins. Learn to lock down your production environment with code-level security strategies.

When you're shipping a custom plugin or a high-traffic theme, relying on a "security scanner" plugin isn't enough. I learned this the hard way after a client’s site got hit by a file-injection attack that bypassed three different "firewall" plugins because they were all looking for signatures instead of structural vulnerabilities.
Hardening a WordPress site you actually ship means treating the core environment like a fortress from day one. It’s about reducing the attack surface before the code even hits the server.
The most common vector for malicious code is the ability for a script to execute in directories where it doesn't belong. WordPress uploads folders are notorious for this. You should never allow PHP execution in /wp-content/uploads/.
If you're managing the server, add this to your Nginx configuration:
NGINXlocation /wp-content/uploads/ { location ~ \.php$ { deny all; } }
If you’re stuck on shared hosting where you can't touch the Nginx config, drop a .htaccess file in your uploads directory with php_flag engine off. It’s a simple move that stops a massive class of exploits dead in their tracks.
The WordPress REST API is powerful, but it’s often an open door. By default, it exposes user data and internal routes that you probably don't need publicly. I’ve seen sites leaking author usernames, which is the first step in a brute-force attack.
I prefer to disable public access to specific endpoints unless they’re explicitly required. Here is how I handle this in my plugin bootstrapper:
PHPadd_filter( 'rest_endpoints', function( $endpoints ) { if ( isset( $endpoints['/wp/v2/users'] ) ) { unset( $endpoints['/wp/v2/users'] ); } if ( isset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] ) ) { unset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] ); } return $endpoints; });
This simple logic prevents attackers from enumerating your user list via the API. If you need to scale this approach across multiple features, make sure you're using hooks and filters done right: Scaling your WordPress code so you don't end up with a spaghetti mess of security logic.

We talk a lot about performance, but security is the flip side of the same coin. An unoptimized database is a target. If you aren't implementing WordPress object caching optimization: A guide for senior engineers, you're not just losing speed—you're leaving the database open to unnecessary query-based injection risks.
I always force DISALLOW_FILE_EDIT and DISALLOW_FILE_MODS in wp-config.php. It sounds basic, but it’s about 90% of the battle when preventing a compromised admin account from turning into a full site takeover.
I once tried to implement a custom, heavy-handed middleware for every request to check for specific headers. It broke compatibility with two major caching plugins and added about 150ms of latency to every single page load.
Don't reinvent the wheel. If you need complex traffic filtering, use Cloudflare or a dedicated WAF. Your job as a WordPress engineer is to make the application layer resilient, not to rebuild the entire networking stack from scratch inside functions.php.
Q: Should I hide the wp-admin URL?
A: It’s security through obscurity. It keeps the log files clean of bot noise, but it doesn't stop a determined attacker. Focus on 2FA and limiting login attempts instead.
Q: What about file permissions? A: My rule is 755 for directories and 644 for files. If you find yourself setting files to 777, you have a configuration issue with your web server user that needs fixing, not a file permission solution.
Q: Is DISALLOW_FILE_EDIT enough?
A: It’s a great start. Pair it with a robust deployment process—like Git-based deployment—so you never have to edit files on the production server in the first place.

Hardening a WordPress site you actually ship is an iterative process. You’ll find new attack vectors as your traffic grows. Next time, I’m planning to look deeper into server-side request forgery (SSRF) protections, as that’s the next frontier for plugin developers. Start with the basics: disable file execution, lock down the REST API, and keep your file edits off the server.
Extending the WordPress REST API with custom endpoints is the best way to decouple your frontend. Learn to build secure, scalable routes like a pro.