How to audit a WordPress site for security weaknesses
A security audit is a written inventory of a working site. It covers what is installed, who can log in, how the site is configured, what it shows from outside, whether a backup restores, and who holds the hosting and domain logins. Each finding gets a date to fix it or a reason to accept it.
- By
- WP Ministry
- Updated
In short
- An audit is a written inventory of a site that is working. It finds known weaknesses before someone else does.
- Start with software. Record every version, every pending update, and every plugin that is inactive, closed or no longer looked after.
- Every administrator should be a person you can name, who still needs that role and uses two-factor login.
- A backup is a finding until someone has restored it and written down the date.
- The hosting account and the domain are part of the site. Record who holds each login and whether renewal is automatic.
- It is not a penetration test, and it cannot find a flaw nobody has reported yet.
A security audit of a WordPress site is an inventory with a record. You go through six areas of a site that is working: what is installed, who can log in, how it is configured, what it shows from outside, whether it could be restored, and who holds the hosting and domain accounts. For each area you write down what you found. Plan an afternoon for it.
Nothing in the audit changes the site. The fixes come afterwards, in an order you choose, and WordPress security: what to do, in order of what matters most has the steps for most of them. If your question is whether someone has already got in, that is a different job: see how to check whether your WordPress site has been hacked.
Keep a record as you go
Open a spreadsheet before you start. Give each finding one row.
| Area | Finding | Action | When |
|---|---|---|---|
| Software | A gallery plugin is inactive and has an update waiting | Delete it | Today |
| Accounts | A designer who left is still an administrator | Delete the account and keep the posts | Today |
| Backups | Backups are taken daily. Nobody has restored one. | Restore the newest to a staging copy | This month |
| Hosting | The site shares a server with other customers' sites | Look again when the plan renews | Accepted |
Record what was in order too, with the date. Never put a password in the record.
The dashboard is enough for most of the audit. The commands on this page need SSH access and WP-CLI, which you can ask your host about. Run them from the site's main folder. None of them installs, updates or deletes anything.
Software: what is installed
WordPress's hardening guide says older versions of WordPress are not maintained with security updates. It also says to keep plugins updated and to delete the ones you do not use. So the first area is a list of everything installed, with its version.
In the dashboard, go to Tools, then Site Health. The Status tab raises "You have plugins waiting to be updated" and "Your site is running an outdated version of PHP, which requires an update" as critical issues. On the Info tab, the WordPress section gives the version, the Server section covers PHP, and "Active Plugins", "Inactive Plugins", "Active Theme" and "Inactive Themes" give each item's version and whether auto-updates are enabled. The tab can copy all of it to the clipboard for your record.
With WP-CLI, it takes five steps.
Step 1: Record the WordPress version and whether a newer one exists
The first command prints the version. The second lists newer versions in a table, or prints a success message when the site is up to date. Put your WordPress and PHP versions into the WordPress and PHP end-of-life checker to see whether they still get security fixes, and until when.
bashwp core version wp core check-updateStep 2: List every plugin and theme
Each row gives the name, the status, whether an update is available, the installed version, the version an update would bring, and whether auto-updates are on. A plugin's status is one of
active,active-network,inactive,must-useanddropin. A theme's isactive,parentorinactive. The last two commands narrow the table to plugins with an update waiting and plugins that are switched off.bashwp plugin list wp theme list wp plugin list --update=available wp plugin list --status=inactiveStep 3: Check whether each plugin is still on WordPress.org
wporg_statusshould readactive. Rely on that value only:closedcan also be shown for a plugin that was never on WordPress.org, such as a paid or custom one, so for anything butactiveopen the plugin's own page on WordPress.org. That page also shows when the plugin was last updated.bashwp plugin list --fields=name,version,wporg_statusStep 4: Look up each plugin in a vulnerability database
WPScan describes its database as cataloging WordPress core, plugin and theme vulnerabilities. Search its plugin list by name, or open
https://wpscan.com/plugin/followed by the plugin's name from the first column above. Each record gives the date it was published, a title that names the affected versions, the version it was "Fixed in", and a CVSS score. Compare "Fixed in" with the version you run.A plugin with no record has nothing on file there. That is not the same as having no flaws.
Step 5: Confirm that WordPress's own files match
This compares WordPress's files with the checksums WordPress.org holds for your version. A clean run prints "Success: WordPress installation verifies against checksums." If a file does not verify, stop the audit and go to the page on checking for a hack, linked at the top.
bashwp core verify-checksums
A finding is any of these:
- WordPress or PHP on a version that no longer gets security fixes, or any update left waiting.
- A plugin or theme that is inactive. Its files are still on the server.
- A plugin on a version lower than the "Fixed in" of a record against it.
- A closed plugin. Its WordPress.org page says "This plugin has been closed and is no longer available for download." A security issue is one of the reasons a plugin is closed.
- A plugin whose last update is years old. It may be abandoned, or small and finished. How to choose a WordPress plugin shows how to read its listing.
- A row marked
must-useordropin, or a plugin from outside WordPress.org, that nobody can explain.
Write down every version, every update waiting, and for each plugin from outside WordPress.org, who installed it and where its updates come from.
Accounts: who can log in
Go to Users. The links above the table filter the list by role. Start with the administrators. From the command line:
wp user list --role=administrator --fields=user_login,user_email,user_registeredWordPress's documentation defines an Administrator as somebody with access to all the administration features of a site, and an Editor as somebody who can publish and manage posts, including other people's. A person who writes and edits rarely needs more than Editor.
Then go to Settings, then General, and read three things. "Anyone can register" decides whether a stranger can create an account. "New User Default Role" is the role a new account is given. "Administration Email Address" is where WordPress sends recovery mode and critical error notices, so it has to be a mailbox your organization can open.
A finding is any of these:
- An account for someone who no longer works on the site.
- One login shared by several people. You cannot remove one of them, and you cannot tell who did what.
- An administrator who only writes or edits.
- An administrator without two-factor login. How to set up two-factor authentication in WordPress shows where to check what each one has enabled.
- Registration open on a site that does not need it, or a default role above Subscriber.
- An administration email address that belongs to a past developer.
Write down each administrator's login, the person behind it, why they need the role, and whether two-factor login is on.
An administrator nobody can account for is a sign of a break-in, not a finding to file. The page on checking for a hack says what to do.
Configuration: how the site is set
| Setting | Where to look | A finding is |
|---|---|---|
| HTTPS | Site Health, Info tab, WordPress section: "Is this site using HTTPS?" | "No", or an http:// address that does not end on https:// |
| File editing in the dashboard | wp config get DISALLOW_FILE_EDIT | Anything other than true |
| Debug output | Site Health, Status tab | "Your site is set to display errors to site visitors" or "Your site is set to log errors to a potentially public file" |
| File permissions | The permissions column in your host's file manager | A folder or file at 777, or a wp-config.php everyone can read |
| XML-RPC | Your list of what connects to the site | xmlrpc.php open when nothing uses it |
- HTTPS. Type the
http://form of your address into the redirect checker. The last address it shows should begin withhttps://. - File editing. WordPress's hardening guide says the dashboard by default lets administrators edit plugin and theme files, and gives a constant that takes that ability from every user. If the line is missing from
wp-config.php, the command answers that the constant "is not defined in the 'wp-config.php' file." Look in the dashboard as well: if you can open a theme or plugin file editor there, editing is on. The security guide linked at the top has the line to add. - Debug output. WordPress's documentation says its debug tools are not recommended on live sites.
wp config get WP_DEBUGshould printfalse, or answer that the constant is not defined. - File permissions. WordPress's guidance is 755 for folders, 644 for files, and a
wp-config.phpthat only you and the web server can read. WordPress file permissions shows how to read the modes and correct them. - XML-RPC. WordPress's guidance calls
xmlrpc.phpa frequent target for password guessing, and names Jetpack and mobile apps as things that use it. How to protect WordPress from brute force attacks shows how to tell whether it answers and how to close it.
Write down each setting as you found it.
What the site shows from outside
Two checks read the site as a stranger does.
- The WordPress site health check reads one page and shows what it shows a visitor: whether it answers, how it is secured, what search engines are told, and which WordPress, theme and plugins it shows.
- The hacked-site check looks for the signs of a break-in that show from outside: visitors from search sent somewhere else, links hidden in the page, and code written to hide what it does.
A finding is an out-of-date version on show. The fix is the update, not hiding the number. Any sign from the second check ends the audit and starts the hack check. Write down the date and what each check returned.
Backups and recovery
WordPress's documentation says a backup has two parts, the database and the files, and that you need both to restore a site. It advises keeping at least three to five recent backups, with copies in different places. Answer these in the record:
- Does each backup hold both parts?
- Where are the copies, and is at least one away from the site's server?
- How many are kept, and how far back do they reach?
- When was one last restored, by whom, and how long did it take?
- Who can start a restore if you cannot be reached?
A finding is a backup with one part missing, copies kept only beside the site, or no date for a restore. How to schedule automatic WordPress backups has the steps for restoring one to a private copy of the site.
The hosting account and the domain
Whoever controls these controls the site, whatever WordPress is set to. List every account the site depends on: the hosting panel, SFTP or SSH, the domain registrar, DNS if it is somewhere else, and wherever backups are stored. For each one, record:
- whose name and email address it is in;
- who knows the password, and whether it is shared;
- whether its login has a second step;
- whether renewal is automatic, and whether the card on file is still valid.
A finding is an account in the name of a past developer or employee, a password passed around by email, a domain that renews only by hand, or file access over plain FTP. The hardening guide says to connect with SFTP, so the password is encrypted on the way.
The same guide notes that on a shared server, a break-in on another site on that server can reach yours. That is a line for the record, and often one to accept. The WordPress maintenance checklist covers reading the domain and certificate dates each quarter.
Turn the findings into a short list
Sort the record into three groups.
Step 1: Fix today
These have a known hole with a fix ready, or leave access with someone who should not have it. Apply waiting updates, above all for a plugin below its "Fixed in" version. Switch off a plugin that was closed for a security issue. Delete the accounts of people who have left: WordPress asks what to do with their posts, so attribute them to another user. Turn off errors shown to visitors. Take a backup before you update anything. How to safely update WordPress, plugins and themes has the order to work in.
Step 2: Fix this month
These need arranging or a trial first: two-factor login for every administrator, lower roles, a replacement for an abandoned plugin, a supported PHP version tried on a staging copy, a restore of the newest backup, and accounts moved into the business's name.
Step 3: Accept, in writing
Some findings stay: the shared server, XML-RPC left open for an app you use, an old plugin that does one small job. For each, write the reason, who decided, and a date to look again.
Keep the record. The next audit starts by comparing with it.
What this audit does not tell you
- It is not a penetration test. In one, a specialist tries to break in, with your permission, and reports how far they got. This audit attempts nothing.
- It does not find a flaw nobody has reported yet. A database and an update notice know only what has been found and published.
- It does not prove nobody is inside. The checksum step covers WordPress's own files and nothing else.
When to get help
- A client or a payment provider asks you for a penetration test. That is work for a specialist firm.
- A finding has no fix you can apply, such as a closed plugin the site depends on.
A care plan from our WordPress security service keeps the site updated, scanned and backed up offsite.
Common questions
Is a security plugin's scan the same as an audit?
No. A scan reads the site. It does not know who has left your business, whether last night's backup restores, or whose name the domain is in. WordPress security plugins compared sets out what each plugin scans.
How often should I do this?
Whenever the people change: a new developer, an agency you have stopped using, a new host. Between audits, the maintenance checklist covers updates, the list of users and a test restore.
Can I do it without SSH or WP-CLI?
Yes, apart from the checksum step. Site Health's Info tab lists the versions, plugins and themes, and the Users screen lists the accounts. For each plugin, open its WordPress.org page and look for a closed notice and the date of its last update.
The audit found nothing. Is the site secure?
It means the things you looked at had no known weakness on the day you looked. WordPress's hardening guide describes security as reducing risk, not removing it.

