How to revoke admin access from someone who no longer needs it

The ticket closed three weeks ago. The contractor’s invoice is paid, the bug is fixed, the customer said thanks. Nobody went back to check whether the Administrator account somebody created to do the work is still sitting in the Users screen, and nobody will, because removing it was never anyone’s job. The login still works and the role is still Administrator. The account opens the site exactly as well today as it did the afternoon somebody needed it.

Removing it takes about ninety seconds. Finding it is the part that takes a plan, because WordPress hands out standing access through two separate systems and cleaning up one of them does nothing to the other.

The two places access lives

You can do the obvious cleanup and still leave a way in. A person who worked on a WordPress site can leave behind a user account, one or more Application Passwords attached to that account, and, if a plugin brokered the access, whatever that plugin created on their behalf.

They are not the same object and they do not clean each other up. Deleting a user account removes the account and its Application Passwords along with it. Revoking an Application Password leaves the account itself untouched: the person can still log in with their regular password and generate a new one.

That gap is where the Rank Math incident of August 2026 lived. Search Engine Journal reported on August 30 that when a site administrator connected to a free rankmath.com account opened the plugin’s Help & Support screen, “the plugin immediately creates a WordPress Application Password,” showing up in the profile as “WAP – Rank Math Support Agent.” Its report notes plainly: “This Application Password does not expire. You cannot turn the ‘Support Agent’ off.” Nobody had a user account to delete, because that wasn’t the object. The credential was a row in a list most site owners have never scrolled to.

Revoking a user account

If the person had a WordPress login, this is the whole job.

  1. Go to Users, then All Users, and filter by Administrator. Read the list out loud if it helps, because the point is to look at every name rather than scan for the one you already suspect.
  2. Hover the row and click Delete.
  3. WordPress asks what to do with anything they authored. Choose Attribute all content to and pick an account that will still exist next year. “Delete all content” is almost never what you want on a site with posts, pages, or WooCommerce orders.
  4. Confirm.

From the command line, the same two steps are:

wp user list --role=administrator --format=csv
wp user delete 123 --reassign=567

WP-CLI’s own documentation for wp user delete is explicit about the reassignment: --reassign=<user-id> is the “User ID to reassign the posts to,” and on multisite the command “only removes the user from the current site. Include --network to also remove the user from the database, but make sure to reassign their posts prior to deleting the user.”

Deleting the account is the only step that also kills the Application Passwords. Demoting the person to Subscriber instead of deleting them is a common instinct, because it preserves the account “just in case”, but every Application Password on that account survives the demotion. Application Passwords authenticate REST API requests, not wp-admin logins, and they carry the capabilities the account holds at the time of the request. A demoted account is a smaller hole that is still open.

Revoking an Application Password

Application Passwords have been in WordPress core since version 5.6, December 2020. They exist so a script or an integration can authenticate without a human’s login password. Each one lives on a user account, is displayed once at creation, and is revocable on its own.

For your own account, go to Users, then Profile. For somebody else’s, go to Users, then All Users, and click Edit on their row. Either way, scroll to the Application Passwords section. WordPress core’s list table gives you five columns (Name, Created, Last Used, Last IP, and Revoke) plus a single Revoke all application passwords control underneath. The Last Used column is the one worth reading before you click anything: WordPress’s own integration guide notes that once a password has been used, “it will keep track of where and when it has been used — the ‘Last Used’ column is accurate to within 24 hours.” A credential that has never been used shows a dash. A credential created eleven months ago and used yesterday is a live integration somebody forgot to tell you about.

From the command line:

wp user application-password list 123 --fields=name,created,last_used
wp user application-password delete 123 6633824d-c1d7-4f79-9dd5-4586f734d69e
wp user application-password delete 123 --all

The --all flag does what it says: WP-CLI documents it as “Delete all of the user’s application password.” Use it on a site you’re cleaning up after an incident. Do not use it casually on a production site with real integrations, because a backup plugin, a headless front end, and a monitoring service may all be authenticating through rows in that table.

The ten-minute audit, per site

Run this on one site now and you will know whether you need to run it on the rest.

Where to lookWhat you’re looking forWhat to do
Users, then All Users, filtered to AdministratorAccounts you can’t attribute to a current personDelete, reassigning content
Users, then All Users, all rolesAccounts registered around the date of a past projectDemote or delete
Users, then Profile, then Application Passwords, per admin accountNames you didn’t create, or any entry beginning “WAP”Revoke individually
Your own account’s Application PasswordsAnything with a Last Used date older than the integration that made itRevoke
Installed plugins with a “Help,” “Support,” or “Connect” screenA support bridge that creates a credential on openCheck the plugin’s own settings, then check Application Passwords again

The last row is the one people skip, and it is the row the August 2026 incident was made of. A support-access feature that creates its credential when a screen loads leaves no trace anywhere a normal offboarding checklist looks.

The checklist works on one site and fails on forty

None of the steps above are hard. That’s the problem with them. They are five minutes of work that has to be initiated by a person who remembers, on every site and after every project, for as long as the site exists. The failure mode is silent. Nothing breaks when nobody runs the audit. The site loads and the customer is happy, so the account sits there unnoticed.

Dormancy is not a theoretical risk here. Patchstack’s April 15, 2026 writeup of the EssentialPlugin supply-chain compromise (code pushed into more than twenty plugins from a single vendor account) records the timeline in one sentence: “Even though the backdoor was planted 7 months ago, it was never used until April 5, 2026.” Seven months of a site looking completely normal, on plugins that were installed and updating on schedule the entire time. “We’ll notice if something’s wrong” is the plan most teams are running on. It has a seven-month track record of being wrong.

Multiply it out and it gets worse rather than better. On one site with one contractor, you’ll remember. A support team logging into forty customer sites a month carries forty separate cleanup obligations, on sites they don’t own, where they can’t see the Users screen unless someone lets them back in to look.

Access that ends without anyone remembering

The alternative is access that carries its own end date. The account is created with the expiry already attached, so removing it is never a task anybody has to hold.

That is the design TrustedLogin is built around, so the cleanup above stops being your team’s job. A customer clicks Grant Access inside a product they already have installed, a button placed there by our free SDK; the site creates a real WordPress account, scoped to the role and duration the vendor configured when they added that SDK; and the site’s own WP-Cron deletes that account when the window closes. The expiry runs on the customer’s site, not on our servers, so access that has already been granted expires on schedule whether or not TrustedLogin is reachable. The customer can also end it early without asking anyone: the SDK adds a Revoke Access action to their Users list and to the admin toolbar in their own wp-admin.

When a customer asks who was in their site last month, you answer from a list instead of from memory. Every session is recorded on both sides: who logged in, to which site, and when, in the TrustedLogin dashboard and in the Connector plugin the vendor runs on their own site. That record answers a question the audit above cannot: who used the account. How the keys are handled, and what we can and can’t see, is written out here.

Where this doesn’t help

It does not fit every team. Retention on the hosted audit log is ninety days by default, which makes it an operational record rather than an archive. And this is built for a team fielding access requests across a customer base. If you log into a client site twice a year, a free temporary-login plugin and a calendar reminder are the right tools, and the walkthrough of all three options is here.

The account you’re about to go delete got created because somebody needed to get in and there was no other way to do it. That part was reasonable. What wasn’t reasonable was the second half of the arrangement, where ending the access became a favor someone had to remember to do for a site they’d already stopped thinking about. Design the ending in at the start, and the audit above is a thing you run once, out of curiosity, instead of every quarter out of obligation.

Similar Posts