Timeline of the Rank Math Support Agent incident from version 1.0.277 shipping on August 26 to the feature being paused on August 31

WordPress Application Passwords: Audit Yours in 5 Minutes

At the end of August, a developer looked inside one of the most widely installed SEO plugins on WordPress and found that opening its help panel handed out a working key to the site. Not a token scoped to one job. A WordPress application password carrying whatever permissions the person clicking already had — which, on most sites, means administrator.

The plugin was Rank Math, it runs on more than four million sites, and the company paused the feature within days. That part of the story is over. The part that is not over is the question it leaves behind for everyone else: you probably have no idea how many application passwords exist on your own site right now, or what created them.

This post covers what an application password actually grants, what happened in the Rank Math case with both sides represented fairly, and — the part almost nobody wrote up — exactly how to audit and revoke these credentials on your own install. We ran the audit on mxchat.ai while writing it and published what came back.

What an application password actually is

Application passwords landed in WordPress 5.6 in December 2020. They solve a real problem: you want a mobile app, a deploy script or an external service to talk to your site over the REST API without handing it your actual login password, and you want to be able to revoke that access later without changing your own credentials.

So far, so sensible. The detail that catches people out is what the credential inherits.

Table showing that WordPress application passwords inherit the creating user's capabilities, with risk rated Critical for Administrator down to Low for Subscriber
An application password is not a reduced-privilege key. It carries the permissions of whoever created it.

An application password is not a lesser key. It authenticates as that user, with that user’s full capability set. A credential created while an administrator is logged in can install plugins, edit other users and read everything in the database. There is no scoping mechanism in core — no “read-only” mode, no per-endpoint restriction. Whoever holds the string can do whatever that account can do.

The second detail is who is allowed to make one. We checked this against WordPress core on our own production install rather than trusting a summary, and the answer is in the source. The function wp_is_application_passwords_available_for_user() ends like this:

return apply_filters( 'wp_is_application_passwords_available_for_user', true, $user );

The default is a hardcoded true. There is no capability check in front of it. The docblock immediately above the function says so in plain words: “By default all users can use Application Passwords.” Every role on your site, down to Subscriber, can mint one unless you have added a filter to stop it.

On a site with open registration, that is worth sitting with for a moment. It is not a vulnerability — it is documented, deliberate behaviour, and a Subscriber’s credential can only do Subscriber things. But it does mean the number of live credentials on a mature site is usually larger than the owner assumes, and nothing in the admin surfaces a site-wide list.

What happened with Rank Math

On 29 August, Sybre Waaijer — the developer behind The SEO Framework, a competing SEO plugin, which is context worth stating — posted publicly about behaviour he had found in Rank Math version 1.0.277. His description of the mechanism:

“When a site administrator whose site is connected to a (free) rankmath.com account opens ‘Help & Support,’ the plugin immediately creates a WordPress Application Password for that user. It sends that password to group.one’s servers.”

group.one is Rank Math’s parent company, and also owns WP Rocket. The credential was labelled WAP – Rank Math Support Agent, and the code lived in vendor/groupone/wap-client/includes/class-app-password-manager.php. Because it inherited the permissions of the user who triggered it, an administrator opening a support panel produced an administrator-level credential.

Timeline of the Rank Math Support Agent incident from version 1.0.277 shipping on August 26 to the feature being paused on August 31
Five days from release to pause.

The sequencing is what drew most of the criticism. Reporting on the incident described the credential being generated before the terms box in the interface had been accepted — so the consent control existed, but it was not the gate.

What Rank Math says

The company paused the feature and published an explanation, and it deserves to be read rather than skipped. Their position, in their words:

  • The Support Agent “needed a way to access your site’s settings” in order to answer support questions inside the plugin.
  • It “was a read-only agent and could not make any changes to your WordPress website.”
  • The credentials were encrypted, “not stored or persisted on our side and used only while an agent session was running.”
  • The permissions were inherited from the user rather than elevated beyond what that user already had.

They also conceded the substance of the complaint: “The concern we heard from some users was that the plugin was not explaining clearly enough that credentials were generated for the AI agents.” Their commitment for the relaunch is that “the agent will clearly and explicitly ask for the required access before any credentials are created or access is granted.”

The line from their write-up that best summarises the whole episode is their own: “When an AI agent is being given permission to create an application password, you should be told clearly and directly what is happening and what you’re allowing.”

Two things are worth stating plainly, because the louder coverage skipped both. No source has reported any evidence that these credentials were misused, and none has reported a breach. And the read-only claim is a meaningful mitigation if accurate — though it describes a restriction Rank Math applied at its own end, not one enforced by the credential, which by WordPress’s design carried full administrator capability.

The guideline question is less clear-cut than the headlines

The rule everyone cited is WordPress’s plugin guideline 7, which we quote in full from the developer handbook:

“In the interest of protecting user privacy, plugins may not contact external servers without explicit and authorized consent.”

That reads decisively against the behaviour. But the same guideline carries an exception that Rank Math has a genuine argument under: when users install, activate, register for and configure a plugin that runs on a hosted service, they are treated as having implicitly consented to that service handling their data. A site owner who had connected a rankmath.com account and opened a panel labelled Help & Support had arguably opted into a support service.

Where that argument gets harder is the specific act of minting an administrator credential and transmitting it. The distance between “I connected an SEO account” and “I issued an admin key to a third party” is exactly the distance the consent screen was supposed to cover, and by the reported sequencing it did not cover it. That is also the gap Rank Math has said it will close.

Audit your own site: the part that actually matters

Every ranking article on this subject explains how to create an application password. Almost none explains how to find the ones already there. That is backwards — creation is a two-minute task you do deliberately, whereas the credentials you did not create deliberately are the ones worth knowing about.

There are three routes, and which one you want depends on how many accounts your site has.

RouteBest forSite-wide view?Speed on 3,000+ users
Users → Profile screenChecking one accountNo — one user at a timeImpractical
wp user application-password listSmall sites, or a shortlistOnly via a loopSlow — loads WordPress per user
Direct wp_usermeta queryFinding which users have anyYes, in one queryInstant

The practical approach on a large site is the third followed by the second: find the handful of accounts that have credentials, then read those in detail.

Through the dashboard

Go to Users → Profile (or Users → Edit for another account) and scroll to Application Passwords. You will see each credential’s name, creation date and last-used date, with a Revoke button beside it.

The catch: this is per user. On a site with a few hundred registered accounts, checking every profile by hand is not realistic, and there is no site-wide view in core. Which is why the second route is the one to use.

Through WP-CLI

WP-CLI has a dedicated command with subcommands for list, get, create, delete and exists. To see one user’s credentials:

wp user application-password list 1 --fields=name,created,last_used

To sweep an entire site, loop over the user list:

for u in $(wp user list --field=ID); do
  n=$(wp user application-password list $u --format=count 2>/dev/null)
  [ "$n" != "0" ] && [ -n "$n" ] && echo "user $u has $n" \
    && wp user application-password list $u --fields=name,created,last_used
done

On a large site that loop is slow, because it spins up WordPress once per user. If you have thousands of accounts, query the database directly instead — application passwords live in a single user meta key:

wp db query "SELECT user_id FROM wp_usermeta
  WHERE meta_key='_application_passwords'
  AND meta_value NOT IN ('','a:0:{}')"

Adjust wp_ to your own table prefix. That returns only the users who actually have credentials, in one query, and you can then run the per-user command on just those.

Reading what you find

What you seeWhat it usually meansDo this
A name you recognise, used recentlyA live integration you set upLeave it
A name you recognise, unused for monthsAn app or device you stopped usingRevoke it
A vendor or product name you never connectedA plugin created it on your behalfInvestigate, then revoke
last_used empty since creationIssued but never exercisedRevoke it
An unfamiliar IP in last_ipWorth explaining before anything elseRevoke and rotate

Revoking is immediate and safe to get wrong in one direction only: if you kill a credential something legitimate was using, that integration stops working and you create a new one. Nothing is destroyed. Given that, err toward revoking.

What we found on mxchat.ai

We ran this on our own production site while writing, partly because it would be poor form to publish an audit guide without doing it. The site runs Rank Math — version 1.0.277.1, on the affected version line.

Audit results for mxchat.ai showing five application passwords on one user, three stale since 2025 and two active, with no SEO plugin credential present
Five credentials across 3,767 registered users, all on one account.

Across 3,767 registered accounts, exactly one user had application passwords: five of them. Four were WooCommerce mobile app clients from two Android handsets, and one was a first-party automation we built and named ourselves. No Support Agent credential was present.

The likeliest reason is simply that the trigger never fired here — the reported behaviour required a connected rankmath.com account plus somebody opening Help & Support during the window the feature was live. Running the affected version was not on its own sufficient. We would not have known that without checking, and neither will you.

The audit did turn up something worth acting on anyway: three of the five credentials have not been used since 2025. Old phones, replaced handsets, credentials nobody revoked when the device went in a drawer. That is the ordinary finding here, and it is the one most sites will get. Stale admin-capable credentials are a standing risk that has nothing to do with any plugin vendor’s behaviour.

Locking it down

If you want to restrict who can create these, the filter is the supported route. To disable application passwords for everyone below administrator:

add_filter( 'wp_is_application_passwords_available_for_user',
  function ( $available, $user ) {
    return user_can( $user, 'manage_options' );
  }, 10, 2 );

To turn the feature off site-wide, filter wp_is_application_passwords_available to false instead. Do that only if nothing legitimately uses the REST API on your site — it will break mobile apps and any external integration that authenticates this way.

A reasonable cadence for most sites: run the sweep quarterly, revoke anything unused for ninety days, and check it after installing or updating any plugin that connects to a vendor account.

How we handle this in MxChat

Since this post argues that vendors should be explicit about what their plugins do, here is ours, stated so it can be checked. We grepped our own plugin source for four separate markers — application_password, wp_create_application, WP_Application_Passwords and app_password — across every PHP and JavaScript file in the plugin. All four return zero matches. MxChat does not create application passwords, does not request them, and has no code path that could.

MxChat does talk to external servers, because that is what an AI chat plugin is: your configured model provider receives conversation content in order to answer it. That is the product working as described, it is documented, and you supply your own API key, so the connection is one you set up knowingly. The distinction we would draw is not “phones home versus doesn’t” — most useful plugins contact something. It is whether the thing being sent is what you agreed to send. A chat message going to the model you chose is that. An admin credential generated by opening a help panel is not.

If you want the detail on what our plugin sends where, it is in the documentation, and the model and key configuration is covered under MxChat Pro.

The broader lesson about plugin trust

The uncomfortable part of this story is that Rank Math is not a fly-by-night operation. It is a mature, popular, commercially serious plugin from a company that owns other well-regarded products, and it shipped this in a release that also closed roughly a dozen security issues. The failure was not competence. It was a consent flow that ran in the wrong order, in a feature built quickly to add an AI agent.

That pattern is going to repeat. Plugins are racing to add AI agents that need to read your site to be useful, and “needs to read your site” is a short step from “creates a credential to do it.” The mechanism at issue here — an inherited-permission credential minted on a UI interaction — is available to every plugin on your site right now.

Which is the same instinct we applied when writing about accessibility overlay widgets: a plugin’s marketing describes its intent, not its behaviour, and the two are only reliably connected by someone checking. If you would rather reduce your exposure than audit it, our guide to handling WordPress SEO without plugins covers how much of this you can do with core alone, and our review of ADA compliance plugins applies the same scrutiny to a different category.

Frequently asked questions

Was my site compromised if I use Rank Math?

Not on the available evidence. No source has reported any misuse of the credentials, and the trigger required a connected rankmath.com account plus somebody opening the Help & Support panel while the feature was live. Run the audit above and look for a credential named WAP – Rank Math Support Agent. If it is not there, the behaviour never fired on your site.

Should I uninstall Rank Math?

That is a bigger decision than this incident justifies on its own. The company paused the feature, published an explanation and committed to an explicit consent step before relaunching. A more proportionate response is to audit your credentials, revoke anything you did not authorise, and decide based on how the relaunched flow actually behaves.

Does revoking an application password log me out?

No. Application passwords are entirely separate from your normal login session. Revoking one only breaks whatever external application was using that specific credential.

Can I see what an application password has been doing?

Only partially. WordPress records a last-used timestamp and last-used IP for each credential, which is enough to spot dormancy and unfamiliar origins, but core keeps no per-request log. For an actual audit trail you need an activity-log plugin.

Do application passwords expire?

No. They are valid until revoked, which is precisely why stale ones accumulate. Nothing in core will ever clean them up for you.

Sources

  • WordPress plugin guideline 7, quoted from the developer handbook at developer.wordpress.org
  • wp_is_application_passwords_available_for_user(), read from WordPress core on our own production install
  • Sybre Waaijer’s public description of the mechanism, as quoted in Search Engine Journal’s reporting
  • Rank Math’s own knowledge base explanation of why the Support Agent was paused
  • Application password data from mxchat.ai, queried directly with WP-CLI on 7 September 2026

Similar Posts