Written by 1:23 am Blog Views: 7

How to Audit Your WordPress Site Security in 5 Minutes

Seven concrete security checks you can run on any WordPress site in under 5 minutes: SSL certificate status, security headers, exposed sensitive files, PHP version, external JavaScript sources, user roles, and file permissions.

Audit WordPress Site Security

Most WordPress security guides tell you to install a security plugin and call it done. That is not a security audit – it is security theater. A real audit means looking at your site the way an attacker would: checking what is exposed, what is misconfigured, and what is one exploit away from being a problem. This guide runs through seven concrete checks you can do in about five minutes, using a free scanner and a handful of CLI commands.

The audience here is WordPress developers and advanced site owners – people who are comfortable with SSH, curl, and reading server output. If you want the quick pass/fail version without touching the command line, the WP Vanguard free scanner covers the first three checks automatically and returns results in under 30 seconds.


Why 5 Minutes Is Enough to Find Real Problems

Automated scanners used by real attackers do not spend hours probing a site. They run fast, targeted checks – looking for low-hanging fruit that most site owners never close. SSL misconfigurations, missing security headers, publicly readable debug.log files, and outdated PHP versions are all things a bot can find in seconds. Your audit should match that speed.

The checks below are ordered by how commonly they are exploited and how quickly they surface problems. Each one maps to a real attack pattern that has been used in documented WordPress compromises. You are not doing academic security research here – you are closing doors that attackers actively try.

  1. SSL certificate status and expiry
  2. Security headers (HTTP response layer)
  3. Exposed sensitive files (xmlrpc.php, debug.log, .env)
  4. PHP version (server runtime risk)
  5. External JavaScript sources (supply chain risk)
  6. User roles and login hardening
  7. File permissions and wp-config.php exposure

Step 1: Check SSL Certificate Status

An expired SSL certificate does not just break the padlock icon – it throws browser warnings that kill user trust immediately and can interrupt REST API calls and webhook delivery. An incorrectly issued certificate (wrong domain, wrong SANs) is just as bad.

The fastest way to check: the WP Vanguard free scanner at wpvanguard.com runs SSL validation as part of its surface scan. Enter your domain, hit scan, and you get the certificate status, expiry date, and issuer in one view. No login required.

For a command-line check with more detail, use openssl directly:

The output gives you the notBefore and notAfter dates. If the cert expires within 30 days, renew it now – most managed hosts auto-renew, but the process can fail silently. Worth confirming.

What to Look For

  • Expiry date within 30 days – schedule renewal
  • Subject CN or SAN does not match your domain – cert mismatch
  • Self-signed issuer on production – browsers will block users
  • HTTP (non-SSL) version of your site still accessible – force HTTPS redirect
  • Mixed content warnings in browser console – images or scripts loading over HTTP on an HTTPS page

If the HTTP version of your site loads without redirecting to HTTPS, that is a separate problem. Add the redirect in your .htaccess above the WordPress block, or handle it at the server level. Mixed content – where some resources load over HTTP on an HTTPS page – can also trigger browser security warnings even when your cert is valid. Check the browser console on your homepage and any cart or checkout pages for mixed content errors.

A cert that expires on a Friday night can take your checkout or API integration down for a full weekend. Set a calendar reminder 45 days before expiry and treat it like an invoice due date.


Step 2: Scan Security Headers

Security headers are HTTP response headers your server sends with every page load. They tell the browser how to handle your content – whether it can be embedded in iframes, what scripts are allowed to run, and whether HTTPS must be enforced. Missing headers are one of the most common findings in any WordPress security audit, and they are easy to fix.

WP Vanguard checks security headers as part of its free surface scan. For a manual check, curl gives you the raw headers in seconds:

Headers That Matter and What They Do

Header What It Does Minimum Value
Strict-Transport-Security Forces HTTPS for future visits max-age=31536000
X-Frame-Options Prevents clickjacking via iframes SAMEORIGIN
X-Content-Type-Options Prevents MIME sniffing attacks nosniff
Content-Security-Policy Controls allowed script/resource sources At minimum default-src 'self'
Referrer-Policy Controls referrer data sent to third parties strict-origin-when-cross-origin
Permissions-Policy Restricts browser feature access Disable unused features

You can add most of these headers in your .htaccess file or in your server’s nginx configuration. The wp-config.php settings guide on this site covers the full header configuration for both Apache and nginx setups, including Content-Security-Policy tuning for WordPress (which is tricky because of inline scripts from plugins).

Content-Security-Policy deserves extra attention. A misconfigured CSP breaks your admin panel, payment widgets, and analytics scripts. Start with report-only mode before enforcing it. Set Content-Security-Policy-Report-Only first, monitor your browser console for a few days to catalogue what your site actually loads, then tighten the policy based on real data.

The Permissions-Policy header is newer and less widely known but increasingly important. It lets you disable browser features your site does not need – camera, microphone, geolocation, payment APIs – so that a compromised third-party script cannot silently activate them. If your site does not use the browser payment API, disable it.

Content-Security-Policy blocks are not plug-and-play. Every third-party script your site loads needs to be accounted for, or you will break functionality silently for some users.


Step 3: Find Exposed Sensitive Files

This is the most underestimated check. Publicly readable xmlrpc.php, debug.log, and .env files are responsible for a significant number of real-world WordPress compromises. These files are not supposed to be accessible from a browser, but they often are because nobody explicitly blocked them.

WP Vanguard’s free scanner checks for exposed files automatically – it tests xmlrpc.php, readme.html, debug.log, and several other paths and flags anything returning a 200 status. Run a free scan at wpvanguard.com to get an instant report.

For a manual check, this script tests the most common exposed paths:

The Files That Get Sites Hacked

xmlrpc.php – The XML-RPC interface is a legacy remote publishing API. It is still present in every WordPress installation. Unless you actively use the WordPress mobile app or a service that requires it (Jetpack sync, some backup tools), it should be blocked. Attackers use it for credential stuffing – the multicall method lets them test hundreds of username/password combinations in a single HTTP request, bypassing login rate limiting.

debug.log – When WP_DEBUG_LOG is enabled in wp-config.php, WordPress writes error output to wp-content/debug.log. This file can contain database credentials, file paths, plugin error traces, and user data. It is never meant to be public-facing, but it often is because the debug config is left on from development. For a full breakdown of every debug constant and how to configure logging safely, see the WordPress debug log guide.

.env – If you use any modern tooling, Bedrock, or a headless WordPress setup, there is likely a .env file with database credentials, API keys, and environment variables. If this is readable from a browser, your site is fully compromised. Block it immediately.

readme.html and license.txt – These expose your exact WordPress version to scanners. Attackers use the version number to look up known CVEs for that release and target unpatched installations.

wp-config.php.bak and wp-config.php~ – Text editors and some deployment tools create backup copies of files with .bak, .old, or tilde suffixes. If your editor created wp-config.php.bak and it is sitting in your webroot, it is publicly readable – unlike wp-config.php itself, which PHP processes on the server side, a .bak file is served as plain text. This is a full credential exposure. Check for these explicitly.

How to Block Them

Add these rules to your .htaccess file, above the # BEGIN WordPress block. See also the full .htaccess security tweaks guide for a more complete ruleset.

For nginx, use deny all; location blocks. The .htaccess approach above only applies to Apache-based hosting.


Step 4: Verify Your PHP Version

Running an end-of-life PHP version is not a misconfiguration – it is a known, documented vulnerability. PHP versions receive security fixes on a defined schedule. Once a version hits end-of-life, security patches stop. Any vulnerabilities discovered after that date remain unpatched permanently.

As of early 2026, PHP 8.0 and below are end-of-life. PHP 8.1 reached end-of-life in December 2024. PHP 8.2 is in security-only maintenance. PHP 8.3 is the current stable release, and PHP 8.4 is in active development. If you are running anything below 8.2, treat it as a critical finding.

PHP Version Status (as of 2026) Action Required
7.4 and below End-of-life (2022 or earlier) Upgrade immediately
8.0 End-of-life (Nov 2023) Upgrade immediately
8.1 End-of-life (Dec 2024) Upgrade as soon as possible
8.2 Security maintenance until Dec 2026 Upgrade to 8.3 before EOL
8.3 Active support Good – keep updated

Upgrading PHP version on managed hosting (Kinsta, WP Engine, Cloudways, SiteGround) is usually done through the hosting control panel. The process takes under five minutes. The risk of upgrading is compatibility issues with plugins that use deprecated functions – always test on a staging environment first.

How to Test Compatibility Before Upgrading

Use WP-CLI to check for PHP compatibility issues before switching versions:

  • Install the PHP Compatibility Checker plugin (wpackagist.org/packages/php-compatibility-checker) on staging
  • Run wp php-compat check --php-version=8.3 if using WP-CLI
  • Review any flagged plugins – most issues are minor and have been fixed in recent plugin versions
  • Update all plugins before upgrading PHP – this eliminates most compatibility issues before they happen

Step 5: Audit External JavaScript Sources

This check is less obvious than the others, but it is increasingly important. Every external JavaScript file your site loads is a potential supply chain attack vector. If the CDN serving that script is compromised, or the npm package behind it gets malicious code injected (it happens more than you think), every visitor to your site runs that code.

The most common sources of external JS on WordPress sites: Google Analytics, Google Tag Manager, Facebook Pixel, Hotjar, Intercom, third-party chat widgets, payment widgets (Stripe, PayPal), and A/B testing tools. Some of these are unavoidable. The question is whether you know what is loading and where it is coming from.

What to Do With the Output

Go through each external JS source and ask:

  1. Do you know what this is? If you do not recognize a domain serving JavaScript to your site, find out. Could be a leftover plugin you thought you deleted.
  2. Is this loaded on every page? Chat widgets and analytics tools often load site-wide when they only need to be on specific pages. Scope them down.
  3. Is it loading from a subdomain you control? Self-hosting scripts (or proxying them through a subdomain) removes the third-party dependency risk.
  4. Does it have Subresource Integrity (SRI) hashes? SRI lets browsers verify that a script has not been tampered with. For scripts from CDNs you do not control, SRI is a meaningful protection layer.

Formjacking – where attackers inject malicious JS that steals form data, including credit card numbers – works by compromising one of the external scripts a site loads. Sites that got hit by Magecart attacks had no idea which third-party script was the entry point until after the breach.

You cannot secure what you cannot see. Most site owners have no idea how many external scripts are loading on their site. The answer is usually more than they think.


Step 6: Audit User Roles and Login Hardening

Most WordPress security guides skip this one entirely – which is exactly why it shows up in breach reports so often. User account misconfigurations are a persistent source of real compromises. An old contractor account still set to Administrator, a test user with a weak password, or the default “admin” username are all things attackers look for specifically.

Check for Rogue Admin Accounts

Run this WP-CLI command to list all users with Administrator or Editor roles:

Go through the output and ask: does every account listed still need that level of access? Former team members, contractors, plugin testing accounts, and staging-to-production migrations all leave behind accounts that nobody audits. Any account you do not recognize or cannot account for should be investigated. Do not delete immediately – reassign to Subscriber first, confirm nothing breaks, then delete.

Also check for accounts registered with suspicious email domains, especially recently created accounts that appeared around the same time as any unexplained site changes. A compromised site often has a backdoor admin account created quietly as part of the intrusion.

The “admin” Username Problem

WordPress used to create the default admin account with the username “admin” during installation. Many older sites still have it. Automated login attacks almost always try “admin” first. If your site has an account with username “admin”, rename it. You cannot rename usernames from the WordPress admin UI – you have to do it via WP-CLI or phpMyAdmin:

Login Page Hardening

The WordPress login page at /wp-login.php is hit by credential stuffing bots constantly. The bots are not sophisticated – they are trying lists of leaked username/password combinations from data breaches. The three things that matter most here:

  • Rate limiting – Limit failed login attempts per IP. Wordfence does this by default. If you do not have a security plugin, add the Limit Login Attempts Reloaded plugin or implement rate limiting at the server level. After 5 failed attempts, an IP should be locked out for at least 20 minutes.
  • Two-factor authentication – Any account with Editor, Admin, or Shop Manager role should have 2FA enabled. WP 2FA is a solid free plugin. There is no good reason to skip this for high-privilege accounts.
  • Application passwords for API access – If anything needs to authenticate to your WordPress REST API, use application passwords (built into WordPress since 5.6) instead of your main account password. These can be revoked individually without changing your login credentials.

One thing that does not help much but gets recommended constantly: changing the login URL by hiding wp-login.php. Security-through-obscurity has limited value – bots can still find the login page by probing REST API endpoints and watching redirects. Focus on rate limiting and 2FA instead, which actually stop attacks rather than just moving the target.


Step 7: Check File Permissions and wp-config.php

File permission misconfigurations create a class of vulnerabilities that are completely invisible to external scanners – you need SSH access to check them. Wrong permissions on wp-config.php, the wp-content directory, or upload folders can let malicious scripts write files or read credentials even without an authentication bypass.

The Correct Permissions

WordPress has well-defined recommended permissions. Anything more permissive than these is a risk:

File or Directory Recommended Permissions Why
wp-config.php 400 or 440 Only readable by owner. No group or public access.
.htaccess 444 Read-only. WordPress rewrites it, but nothing else should modify it.
WordPress core files 644 (files), 755 (directories) Owner can write, group and public can read only.
wp-content/uploads 755 (directories), 644 (files) Web server needs to write uploads, but no execute on uploaded files.
wp-content/plugins 755 (directories), 644 (files) Plugins should not be world-writable.

Check your current permissions via SSH with this script:

If you find directories with 777 permissions, that is a high-severity finding. World-writable directories let any process running on the server write files there – including malicious scripts placed by attackers who have access to other sites on the same shared host (cross-site contamination is common on budget shared hosting).

Hardening wp-config.php

Beyond file permissions, wp-config.php itself has several site settings that directly affect security posture. At minimum, verify these are set correctly:

  • WP_DEBUG should be false on production. Debug output exposes server paths and can leak credentials.
  • DISALLOW_FILE_EDIT set to true disables the built-in theme and plugin editor in the WordPress admin. If an attacker gets admin access, this editor is the first thing they use to inject backdoor code.
  • DISALLOW_FILE_MODS set to true also blocks plugin and theme installation/update from the admin – useful on hardened production sites where all changes go through a deployment pipeline.
  • Your database prefix should not be the default wp_. This does not stop determined attackers, but it prevents a class of automated SQL injection attacks that hardcode the default prefix.

For the complete wp-config.php hardening reference with every constant explained, see the wp-config.php hidden settings guide.


Running All 7 Checks in Under 5 Minutes

If you want to run through these checks fast, the quickest path is to start with the WP Vanguard free scanner at wpvanguard.com. Enter your domain and run a free surface scan – it checks SSL status, security headers, exposed files, and more, and returns a structured report in under 30 seconds. No account required for the free scan.

For the checks the scanner does not cover (PHP version, external JS audit, user roles, file permissions), the CLI scripts above take about three minutes combined. Here is the full sequence:

  1. Run WP Vanguard free scan – covers SSL, headers, exposed files (30 seconds)
  2. Check PHP version via WP-CLI or SSH (30 seconds)
  3. Run the external JS audit script against your homepage (1 minute)
  4. List admin users and verify each account (1 minute)
  5. Check file permissions on wp-config.php and wp-content (30 seconds)
  6. Review the exposed files script output if you want CLI confirmation (30 seconds)
  7. Document any findings and schedule fixes

How to Prioritize What You Find

Not every finding is equally urgent. Use this triage order:

Finding Severity Fix Timeline
Exposed .env file (200 status) Critical Fix immediately – site is compromised
World-writable directories (777) Critical Fix immediately – active exploit risk
Unrecognized admin account Critical Investigate and remove today
Exposed debug.log (200 status) High Block today
PHP 7.x or 8.0 High Upgrade within 1 week
SSL cert expires within 30 days High Renew within 48 hours
wp-config.php permissions 644 or 755 High Tighten to 440 today
xmlrpc.php accessible (200) Medium-High Block this week
No 2FA on admin accounts Medium-High Enable within 1 week
Username is “admin” Medium Rename this week
Missing HSTS header Medium Add within 2 weeks
Missing X-Frame-Options Medium Add within 2 weeks
Unrecognized external JS Medium Investigate and resolve
readme.html accessible (200) Low Block during next maintenance

Security Plugin Comparison: What Each One Actually Covers

Security plugins are not interchangeable. Each one has different strengths, and none of them cover everything. If you install one expecting it to handle your entire security posture, you will miss gaps. This table maps the major options to what they actually do – and what they do not.

Feature Wordfence Free Sucuri Free iThemes Security WP Vanguard
Malware file scanning Yes (limited depth) No (paid only) Yes No
Login rate limiting Yes No Yes No
2FA support Yes (paid) No Yes No
Security headers check No No Partial Yes
SSL certificate check No No No Yes
Exposed file detection Partial No No Yes
PHP version check No No No Yes
External JS audit No No No No
File permission check Partial No Yes No
WAF (Web App Firewall) Yes (limited free) Yes (paid only) No No
Real-time threat intel Yes Yes (paid) No No
No WordPress install needed No No No Yes

The practical conclusion: no single tool covers everything. A reasonable stack for most WordPress sites is Wordfence Free (for file scanning and login protection) combined with a surface scanner like WP Vanguard (for SSL, headers, and exposed file checks). For sites processing payments or handling sensitive data, add a WAF layer – either through Sucuri’s paid CDN or Cloudflare’s WAF rules.


Automating the Audit

Running this manually once is useful. Running it on a schedule is better. Security posture degrades over time – a plugin update can reintroduce a vulnerability, a developer might flip on debug mode and forget to turn it off, a new contractor gets added with more permissions than needed. Scheduled checks catch these regressions before they become incidents.

cron + curl script – Set up a server cron job that runs the exposed files check and emails you if any return 200. The script runs a curl check against your domain’s sensitive paths and sends an alert if anything returns a 200 status code. Takes 30 minutes to set up, runs forever. This is the most direct approach for developers who prefer not to depend on third-party monitoring tools.

WP Vanguard scheduled monitoring – The scanner can watch your site on a schedule and alert you when SSL status, exposed files, or security headers change. Particularly useful for client sites or sites you manage but do not actively develop – passive monitoring without maintaining your own scripts.

GitHub Actions on deployment – If your site uses a CI/CD pipeline, add a security check step that runs after each deployment. This catches configuration regressions before they go live. A simple step that curls for exposed files and checks response codes adds under 30 seconds to a deployment pipeline and catches a wide class of misconfigurations.

Security plugin scan – Wordfence, Sucuri, and iThemes Security all include file integrity checks and scan for known malware signatures. These complement the checks above but do not replace them – they focus on file-level threats, not configuration-level gaps.

WP-CLI audit scripts in a Makefile – If you manage multiple WordPress sites, a simple Makefile target that runs a sequence of WP-CLI security checks across all sites in your inventory gives you a consistent audit baseline. Run it weekly as part of maintenance.

What This Audit Does Not Cover

To be clear about scope: this guide covers surface-level configuration checks and common account misconfigurations. It does not:

  • Scan plugin files for malware or backdoors
  • Check database for injected content or rogue admin accounts created via SQL injection
  • Test for SQL injection or XSS vulnerabilities in custom code
  • Review plugin-specific security configurations (WooCommerce, membership plugins, form plugins all have their own security surface)
  • Assess your hosting environment’s network-level security

For those deeper checks, the wp-config.php settings guide on this site covers the server-level configuration side. For malware scanning and database integrity, you need either a dedicated security plugin or a hands-on manual review via SSH.


Quick Reference: Security Audit Checklist

  • SSL certificate valid and not expiring within 30 days
  • HTTP redirects to HTTPS (no mixed content)
  • Strict-Transport-Security header present
  • X-Frame-Options: SAMEORIGIN set
  • X-Content-Type-Options: nosniff set
  • Content-Security-Policy configured (even if report-only)
  • Permissions-Policy set to disable unused browser features
  • xmlrpc.php returns 403 or 404
  • debug.log not publicly readable
  • .env file not publicly readable
  • wp-config.php backup files (.bak, .old) not publicly readable
  • readme.html returns 403 or 404
  • PHP 8.2 or higher running
  • All external JS sources identified and reviewed
  • No unrecognized third-party scripts loading
  • All admin accounts belong to current team members
  • No account with username “admin”
  • 2FA enabled on all Administrator and Editor accounts
  • wp-config.php permissions set to 400 or 440
  • No world-writable (777) directories in the WordPress install
  • WP_DEBUG disabled on production
  • DISALLOW_FILE_EDIT set to true in wp-config.php

Frequently Asked Questions

Do I need a security plugin if I run these checks manually?

The manual checks in this guide cover configuration-level gaps that most security plugins do not check at all – SSL status, missing HTTP headers, exposed file paths, PHP version, and external JS sources. What security plugins add on top of that is file integrity monitoring (detecting if WordPress core files have been modified), real-time threat feed blocking (blocking IPs known to run attacks), and malware signature scanning. These are complementary tools. For a production site handling any real traffic, running both is more thorough than picking one. The most common gap in sites that only use security plugins: they have Wordfence installed with a clean scan report, but their debug.log is publicly readable, their SSL cert has 8 days left, and their xmlrpc.php is accessible. Wordfence does not check any of those things.

My security plugin says the site is clean. Why would I bother with this audit?

A security plugin scan result of “clean” means the plugin found no malware signatures or file modifications that match its database of known threats. It says nothing about your HTTP security headers, your PHP version, whether your debug.log is publicly readable, or whether your SSL cert is about to expire. These are configuration-level issues, not file-level threats. A site can pass a Wordfence full scan and still have critical findings in an audit like this one. The two types of checks address different things. Security plugin scans are reactive – they look for evidence of past compromise. Configuration audits are preventative – they close doors before attackers try them.

Is blocking xmlrpc.php safe? Won’t it break Jetpack or other plugins?

Blocking all access to xmlrpc.php is safe for most sites. The WordPress mobile app does use XML-RPC, so if you or your team publishes from the mobile app, you need to keep it accessible. Jetpack on older versions used XML-RPC for some sync operations, but modern Jetpack (version 9.0 and above) has moved to the REST API and no longer requires XML-RPC. ManageWP and MainWP also use XML-RPC for remote management – if you use these, check whether your version supports REST API mode before blocking. For everything else – including most WooCommerce integrations and page builder plugins – XML-RPC is not needed. The safest approach: block it, test your main workflows over 24 hours, unblock if something breaks. Most sites find nothing breaks.

How often should I run this audit?

For sites with active development or frequent plugin updates, run the full audit monthly. For stable production sites with infrequent changes, quarterly is sufficient as a baseline. The automated version – a cron script checking exposed files and SSL expiry – should run weekly regardless. The things that change unexpectedly (SSL cert auto-renewal failures, a plugin update that re-enables XML-RPC, debug mode left on after troubleshooting) are the ones that need monitoring between manual audits. High-value targets like WooCommerce stores with active transactions, membership sites, or any site storing PII should also run a malware scan monthly in addition to the configuration checks here.

My host says they handle security. Do I still need to do this?

Managed WordPress hosts (Kinsta, WP Engine, Flywheel, Pressidium) handle a real slice of security at the infrastructure level: DDoS mitigation, server-level malware scanning, network firewalls, and server software patching. What they do not control is your application-level configuration. Your HTTP security headers are set by your theme or a plugin – the host does not configure those for you. Your debug.log being publicly readable is a WordPress configuration issue, not a server issue. Your “admin” username is your account. Your PHP compatibility testing before an upgrade is your responsibility, even if the host applies the upgrade. Managed hosting raises the floor of security significantly, but it does not replace an application-level audit.

What should I do first if I find multiple critical issues?

Triage by exploit impact, not by how easy something is to fix. An exposed .env file takes 30 seconds to block but represents a full credential compromise – fix it first, regardless of what else you find. World-writable directories and unrecognized admin accounts are the next priority. SSL cert expiry is urgent if the window is under 7 days. After the critical issues are closed, work through the high-severity items (PHP version, exposed debug.log, missing security headers). The medium and low severity items can go on a backlog scheduled for the next maintenance window. Document every finding with a timestamp and the fix applied – this becomes your audit trail if you ever need to demonstrate security posture to a client, auditor, or insurance provider.


Do the Audit, Then Fix What You Find

Security audits are only useful if you act on the results. The most common trap is finding issues, documenting them, and then letting the list sit. Use the severity table above to decide what gets fixed today versus what goes on the backlog.

Start with the WP Vanguard free scan at wpvanguard.com – it gives you a structured starting point without any setup. Combine that with the CLI checks in this guide for the full picture. Most sites find at least one finding worth fixing in the first scan. The goal is to close those gaps before someone else finds them for you.

For ongoing hardening beyond what this audit covers, the .htaccess security guide and the wp-config.php settings guide on TweaksWP are the logical next steps.

Visited 7 times, 1 visit(s) today

Last modified: March 26, 2026