What user enumeration is
Enumeration means collecting a list of valid usernames from a site. An attacker does not need to guess usernames if the site hands them over, and with a username in hand, guessing a password is half as hard.
Many of the leaks are features, not bugs. WordPress shows author names so readers can find an author's posts. The problem is that the same features can reveal the login name behind the account.
Why it matters
Knowing that an account called editor-jane exists, and that it is an administrator, lets an attacker aim password guessing, phishing and credential stuffing at it. A bot that already has your administrator's username also gets past defences that only block the username admin.
Blocking enumeration does not make a weak password strong. It simply removes a free hint.
The ways WordPress leaks usernames
There are four common leaks.
- Author archives. Visiting
/?author=1redirects to/author/username/, which shows the author slug, and by default that slug is the login name. - The REST API.
/wp-json/wp/v2/userslists users who have published posts, with their names and slugs. - User sitemaps. Since WordPress 5.5 the built-in sitemap includes a users page at
/wp-sitemap-users-1.xml. - Login errors. Different messages for a wrong username and a wrong password reveal whether an account exists. Password reset forms can leak the same way.
- Embeds and feeds. oEmbed data and some feeds include author names and links.
Test your own site
Check each leak with a request from a signed-out browser or a command line. If any of them returns a real username, you have found a leak.
# Author redirect: look for a Location header containing /author/
curl -sI "https://yoursite.com/?author=1"
# REST API user list: a JSON list means it is open
curl -s "https://yoursite.com/wp-json/wp/v2/users"
# User sitemap
curl -sI "https://yoursite.com/wp-sitemap-users-1.xml"Stop WordPress user enumeration in code
You can close the REST API and sitemap leaks with a few lines in a small plugin or must-use plugin. Only change what signed-out visitors see, so the block editor and other admin tools keep working.
Check that your theme or an app does not rely on the public users endpoint before you remove it.
add_filter( 'rest_endpoints', function ( $endpoints ) {
if ( ! is_user_logged_in() ) {
unset( $endpoints['/wp/v2/users'] );
unset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] );
}
return $endpoints;
} );
add_filter( 'wp_sitemaps_add_provider', function ( $provider, $name ) {
return ( 'users' === $name ) ? false : $provider;
}, 10, 2 );Make login errors vague
A message such as 'Unknown username' tells an attacker that the account does not exist, while 'The password you entered is incorrect' confirms that it does. Show one message for both, for example that the username or password is wrong. Do the same on the password reset form: say that an email will be sent if the account exists.
add_filter( 'login_errors', function () {
return 'The username or password is incorrect.';
} );Go further with display names and slugs
Even with every leak closed, a login name that is also the public display name or the author slug is still public. Give every user a display name that differs from their login, and avoid logins that match an email address or the name shown on posts.
Pair all of this with two-factor sign-in and lockouts, because a clever attacker can still find usernames from other places, such as your contact page or a data breach.
WordPress user enumeration: questions
Is user enumeration a vulnerability in WordPress?
WordPress treats most of it as expected behaviour, because author pages and the REST API are features. It is still worth closing, because the usernames help attackers.
Will blocking enumeration break my site?
Not for visitors, but it can break themes or apps that read the public users endpoint, and author archives on sites with plain permalinks. Test after you change it.
Are display names the same as usernames?
No. The display name is shown publicly, while the login name is used to sign in. Make sure they are different, and check the author slug as well.
Does the REST API need to be disabled completely?
No. Only hide the users endpoints from signed-out visitors. Disabling the whole REST API breaks the block editor, forms and many plugins.
How can I check if my site leaks usernames?
Run the three requests in this guide, or use the free security check at /tools/security-check, which looks for a user list and other common leaks.