Can anyone read a WordPress site's usernames?
A WordPress install publishes its account names, and on most sites nobody has ever changed that. Two routes do it. The REST endpoint at /wp-json/wp/v2/users answers an anonymous request with a list of accounts, and a request for /?author=1 redirects to that author's archive, whose address is the login name. Neither requires a password, a tool or any skill at all.
Why a username matters
A login is two secrets, and most advice concentrates on the second one. The first is the account name, and where it is published the attacker is left with a single unknown instead of two. That is the whole difference between guessing at a site and running a targeted attempt against a known account.
It compounds with what else WordPress leaves open. An endpoint that accepts many password attempts per request is a nuisance while the account names are unknown, and a real risk once they are not. The pair is why automated attacks against WordPress start with the same two requests before they try a single password.
There is a second cost that has nothing to do with break-ins. The list carries display names, which are frequently people's real names, and the roles they hold. That is a staff directory published by accident, and it is what a convincing phishing message is built from.
Counted, not collected
A check that reports leaked account names has an obvious problem: the report then contains the account names. It would travel by email, sit in a database and get forwarded to whoever is fixing the site, which is a scanner publishing the thing it is warning about.
CheckWeb reports the count and exactly one example. The count is what makes the finding real (six accounts is a different site from one), and the single example is what makes it checkable in a browser without taking the scanner's word for it. The rest are counted and discarded, and a test asserts that no second name reaches the finding, the database or the PDF. Display names are not used as the example, because they are usually somebody's real name.
The false-positive work is on the other side. A restricted REST endpoint answering 401 or 403 is the good outcome and is not reported; neither is an empty array, nor a document that parses but carries no accounts. For the author route, a redirect on its own means nothing, because a great many sites redirect everything: what counts is a redirect into an author archive on this same domain, carrying a name. A redirect to the home page, to the https version, or to somebody else's site is not this finding.
How it looks in the report
The finding names which route worked, how many accounts came back, and one example so the result can be confirmed first-hand. It sits at medium: on its own a published username is not a way in, and it makes everything that is a way in considerably cheaper.
Both routes are ordinary reads. The REST endpoint is a public API answering a normal request, and the author route is one redirect that is read rather than followed. No login is attempted with any name that comes back, on this site or anywhere else.
It runs only where the site is recognised as WordPress, and only after domain ownership is verified.
WordPress account names are public
The REST users endpoint answered an anonymous request with a list of accounts. A login name is half of a login, and it is the half that is normally guessed. Restrict the endpoint to signed-in users and stop the author redirect.
GET /wp-json/wp/v2/users → HTTP 200, JSON array of 4 user accounts · one example: "alice" (3 further accounts counted, not recorded)
Published vs private
Published
A default install. The REST endpoint returns every account with its id, display name and slug, and /?author=1 redirects to /author/alice/, which states that the login is alice. Both work in a browser with no tools, and neither leaves anything in the site's own logs that looks unusual.
Private
The users endpoint requires authentication and answers 401 to anonymous callers, and a request carrying ?author= goes to the home page instead of an archive. The site works exactly as before: nothing a visitor does needs either of those to be public.
Worth checking separately: where the display name is the same as the login, the author archive still publishes it even after the redirect is closed. Changing the display name is the fix, and it changes nothing else.
How to close it
- Restrict the REST users endpoint to signed-in callers. Most security plugins have a single switch for this, usually called disable user enumeration; without one, filter rest_endpoints to remove /wp/v2/users and /wp/v2/users/(?P<id>[\d]+) when the request is not authenticated.
- Stop the author redirect. Redirect any front-end request carrying an author query parameter to the home page, which is one short hook or one rewrite rule at the web server.
- Give each account a display name that differs from its login. This is the step most often skipped, and without it the author archive keeps publishing the login for anyone who finds the page another way. It takes a minute per user and affects nothing else.
- Then close what makes a known username worth having. Guessing is only cheap while an endpoint accepts attempts in bulk, which is the other WordPress default worth turning off. (XML-RPC enabled covers that.)
- Put two-factor authentication on the accounts that can publish or install. A published username stops being interesting once the password is not sufficient on its own, and this is the step that holds even if something else is missed.
- Re-run the audit and confirm both routes are closed. They are closed independently, and shutting one while the other still answers is the common half-fix.
Run a free scan
The free passive scan grades headers, TLS and known CVEs on any site in about thirty seconds, with no signup. Verifying that a domain is owned adds the deep scan, which checks both enumeration routes and reports the count with a single example rather than the list.
Check my websiteFAQ
- Is a public username actually a problem?
- Not on its own, and that is why it is reported at medium rather than higher. What it does is remove one of the two unknowns in a login, which makes every password-guessing route worth an attacker's time. Combined with an endpoint that accepts attempts in bulk, it is how most WordPress compromises begin.
- Does the scan store the usernames it finds?
- No. The count is kept and one example is shown so the finding can be confirmed; every other name is discarded, and a test asserts that no second name reaches the finding, the database or the PDF.
- Why not just rename the admin account?
- It helps, and it does not close either route. A renamed account is published under its new name just as readily, so the fix is to stop publishing rather than to pick a name that is harder to guess.
- Will restricting the REST endpoint break the site?
- Not for visitors. The users endpoint exists for the block editor and for integrations that authenticate, and both keep working because both are signed in. Front-end pages do not read it. Where a theme genuinely does, an author archive or a page template is the supported way to show contributors.
Related checks
- XML-RPC enabledWhat makes a known username worth having: an endpoint that accepts many password attempts in a single request.
- WordPress securityThe wider picture: core and plugin versions, known CVEs, and the rest of what a default install exposes.
- Exposed secrets and API keysThe other half of a WordPress audit: wp-config backups, database dumps and the files that answer a plain request.