---
title: "WordPress User Security: Audit Accounts, Roles and Passwords"
description: "A quarterly WordPress user audit: find every admin, remove unused accounts, enforce strong passwords, and review the app passwords that bypass 2FA."
url: "https://skybootstrap.com/wordpress-user-security/"
canonical_url: "https://skybootstrap.com/wordpress-user-security/"
date: "2026-10-27T15:56:00+06:00"
modified: "2026-10-27T16:16:22+06:00"
author: Skybootstrap Team
type: article
site: SkyBootstrap
language: en-US
---

# WordPress User Security: Audit Accounts, Roles and Passwords

A WordPress user audit means finding every administrator, removing accounts nobody uses, forcing strong passwords, and reviewing the application passwords that bypass two-factor login. The surprises on our test site: WordPress keeps no last-login date, it will accept the password `abc` from a request that skips the browser’s warning, and its REST API lists your usernames to anyone. This guide is a quarterly checklist for any site with more than one user, each step tested on WordPress 7.1.3.

## Find every administrator

Start by listing every administrator account, because each one is a full key to the site and an attacker only needs one. Sites accumulate admins over the years: former staff, a developer who set things up, a plugin that created one.

List them in seconds. With WP-CLI: `wp user list --role=administrator --fields=ID,user_login,user_email,user_registered`. In the dashboard, open **Users → All Users** and click the **Administrator** filter. On our test site, this returned the admin accounts with their emails and registration dates (test T1).

![The Users screen filtered to administrators](https://skybootstrap.com/wp-content/uploads/2026/10/users-administrators-1024x640.webp "The administrators list on our test site")

For each admin, ask: does this person still need full access, and do I recognize the account at all? An administrator you can’t place is the first thing to investigate, because an unexpected admin is a classic sign of a compromise ([cleaning up a hacked site](https://skybootstrap.com/wordpress-site-hacked/)). The goal is the smallest possible number of administrators, each one a real, current person.

## WordPress keeps no last-login date

You can’t tell which accounts are inactive from WordPress alone, because core records no last-login timestamp, so “delete inactive users” needs a plugin or another signal. People assume there’s a last-seen column; there isn’t.

We checked on the test site (test T2). WordPress stores `session_tokens` user meta for accounts with a live session, but nothing that records when an account last logged in, and a grep of core for `last_login` found nothing. An account that logged in once two years ago looks identical to one used daily.

So to find inactive accounts you need either a plugin that logs logins (an activity-log or last-login plugin, going forward) or an outside signal: has this person left the team, does this email still work, has the account published or edited anything. Don’t wait for a tool to decide. If you don’t recognize an account or know its owner has moved on, that’s reason enough to act.

## Remove or demote accounts you don’t need

For an account nobody needs, either delete it and reassign its content, or demote it to a role with less power. Every extra account is extra attack surface, and old admin accounts with weak or reused passwords are a favorite way in.

Two tested options:

- **Delete and reassign.** On our test site, `wp user delete olddev --reassign=1` removed the account and reassigned its posts to another user; the deleted account’s user-meta rows (its sessions and application passwords included) were gone too (test T7). In the dashboard, deleting a user prompts you to attribute their content to someone else, so nothing is lost.
- **Demote instead of delete.** If you want to keep the account and its authorship but remove its power, drop its role. On our test, `wp user set-role shopmgr author` set a user’s role to author (test T8). This suits a person who still needs to log in but no longer needs editor or admin rights.

The principle is least privilege: give every account the lowest role that lets it do its job. A contributor who only writes drafts doesn’t need Editor; a shop manager doesn’t need Administrator. Role definitions themselves are a separate topic from this security audit, covered in the user-roles explainer rather than here.

## Enforce strong passwords (and know the gap)

Push every user to a strong password, but understand that WordPress will not strictly enforce one on the server, so the password strength meter is guidance, not a wall. This gap is worth seeing.

WordPress shows a strength meter and, for a weak password, makes you tick a “Confirm use of weak password” box. We tested whether that actually stops a weak password (test T6). It does not. On our test site, saving the password `123456` with the confirmation box ticked succeeded, and the account then logged in with `123456`. Worse, a request that simply omitted the weak-password field entirely, the kind a script makes, set the password to `abc` and that logged in too (test T6b). The meter is a front-end nudge; the server accepts almost anything.

So enforcing strong passwords means more than trusting the meter:

- **Set the expectation** and use a password manager for every admin account, with long, unique passwords.
- **Add real enforcement** if the site has many users: a plugin can require a minimum length and complexity on the server side, which core doesn’t.
- **Lean on two-factor authentication**, which makes a weak password far less dangerous because the password alone isn’t enough. It’s the most reliable fix for human password habits; see [setting up two-factor authentication](https://skybootstrap.com/wordpress-two-factor-authentication/).

## Review application passwords

Audit every account’s application passwords, the separate credentials for apps and scripts, because they bypass two-factor authentication and often outlive the integration that created them. This is the step most audits miss.

On our test site, listing them per user showed each application password’s name, creation date, and last use (test T3): `wp user application-password list demo --fields=name,created,last_used,last_ip`, or in the dashboard under **Users → Profile → Application Passwords**.

![The Application Passwords section of a user profile](https://skybootstrap.com/wp-content/uploads/2026/10/application-passwords-1024x376.webp "The Application Passwords section of a user profile")

Why they matter: an application password is a full login that skips 2FA entirely, even on an account with 2FA switched on (shown in our setting up two-factor authentication guide). So a leaked integration key is a full login that your 2FA does nothing to stop. For each one, check: do I recognize it, when was it last used, and does the service that owns it still exist? Delete any you can’t place or that belong to a retired tool. Give each integration its own named password so you can revoke one without breaking the others.

## Stop leaking usernames

Close the ways WordPress hands out your usernames, because an attacker who knows your login names only has to guess passwords. A default install gives them away freely.

We confirmed the leaks on the test site with pretty permalinks on (test T4b):

- `/?author=1` returned a 301 redirect to `/author/demo/`, exposing the account’s slug. That slug defaults to the login name, so on most sites it hands over a real username.
- The REST route `/wp-json/wp/v2/users` returned a JSON list of account slugs and display names to an unauthenticated request.

Both are on by default. To reduce the exposure: set display names and slugs that differ from login names (so author pages don’t reveal the login), and consider a security plugin or a small snippet that restricts the `users` REST endpoint to logged-in requests. This won’t stop a determined attacker, since usernames can leak other ways, but it removes the easy enumeration that feeds automated attacks. Pair it with login rate limiting ([limiting login attempts](https://skybootstrap.com/wordpress-brute-force-protection/)).

## Log everyone out after the audit

When you finish an audit, especially after a staff change or a scare, end every active session so any stolen cookie dies. Changing passwords doesn’t always kill existing sessions; this does.

On our test site, `wp user session destroy writer1 --all` ended that user’s sessions, and a request with the old session cookie was immediately bounced to the login page (test T5). For all users at once, rotating the secret keys in `wp-config.php` logs out everyone in one step, covered in [wp-config.php security settings](https://skybootstrap.com/wp-config-php-security/). In the dashboard, a user’s profile has a “Log Out Everywhere Else” button for their own sessions.

## Frequently Asked Questions

### How do I find all administrator accounts in WordPress?

Open Users, All Users, and click the Administrator filter, or with WP-CLI run wp user list –role=administrator. Review each one: does this person still need full access, and do you recognise the account? An administrator you can’t place is the first thing to investigate, since an unexpected admin is a classic sign of a compromise. Keep the number of admins as small as possible.

### Does WordPress record when a user last logged in?

No. WordPress core keeps no last-login timestamp, so you can’t spot inactive accounts from the dashboard alone; we confirmed there’s no such field in core. To find dormant accounts you need a plugin that logs logins, or an outside signal such as whether the person has left the team. Don’t wait for a tool: if you don’t recognise an account or know its owner moved on, act on it.

### Will WordPress stop me from setting a weak password?

No. The strength meter is only a front-end nudge. On our test site, saving the password 123456 with the “confirm weak password” box ticked succeeded, and a scripted request that skipped the check set a password to abc. For real enforcement on a multi-user site, add a plugin that requires a minimum length and complexity on the server, and rely on two-factor authentication as the backstop.

### Why do application passwords matter in a user audit?

Because they bypass two-factor authentication. An application password logs straight into the REST API and XML-RPC with no second factor, even on an account with 2FA on, so a leaked integration key is a full login your 2FA won’t stop. Review them on every account under Users, Profile, delete any you can’t place or that belong to retired tools, and give each integration its own.

## The quarterly checklist

Run this checklist every quarter, and immediately after anyone leaves the team:

1. List administrators; remove or demote any you don’t need.
2. Find inactive accounts (via a login-logging plugin or team knowledge) and delete or demote them, reassigning content.
3. Confirm every account uses a strong, unique password; add server-side enforcement if you have many users.
4. Review application passwords on every account; delete unknown or retired ones.
5. Reduce username leakage (display names, restricted REST endpoint).
6. Log everyone out to kill stale sessions.

Account security is where most real break-ins actually start, through a weak password or a forgotten admin, so this audit matters more than most of the server-level hardening. It pairs with two-factor authentication (our setting up two-factor authentication guide) and login rate limiting (our limiting login attempts guide). The full order is in [the full WordPress security checklist](https://skybootstrap.com/wordpress-security-checklist/).