WordPress MCP plugin vulnerabilities: the 2026 pattern and how to check any plugin
What happened to WordPress MCP plugins in 2026?
Four plugins, two weeks, one bug. Between 19 August and 3 September 2026, four WordPress MCP plugins published authorization-bypass advisories with the same shape: a low-privilege user — a subscriber, or the holder of an OAuth bearer token — could call administrator-level MCP tools because the tool handler never re-checked the caller's capabilities. None was an exotic exploit. Each was a missing permission check at a new entry point.
The table lists them as the advisories describe them. Every project shipped or is shipping a patch; a quick fix is what a healthy project does, and nothing here is an argument against any of them.
| Plugin | Affected | Advisory | Severity | Published | Fixed in |
|---|---|---|---|---|---|
| AI Engine | 3.6.0 and earlier | CVE-2026-75796 (opens in new tab) — a multisite sub-site administrator could reach network-admin operations through the MCP User Tools | CVSS 7.2 | August 2026 | 3.6.1 |
| Royal MCP | before 1.4.26 | Subscriber+ insufficient authorization in MCP tools, reported by Patchstack (opens in new tab) | CVSS 8.1 | 24 August 2026 | 1.4.26 |
| Agentimus (AI SEO, llms.txt & MCP) | 1.51.0 and earlier | CVE-2026-84779 (opens in new tab) — subscriber-level broken access control | CVSS 8.1 | 3 September 2026 | see advisory |
| MountDev AI MCP Connector | 1.6.5 and earlier | CVE-2026-85306 (opens in new tab) — missing authorization | CVSS 6.5 | 3 September 2026 | see advisory |
Three of the four had been here before. AI Engine's earlier CVE-2026-8719 (CVSS 8.8) let a subscriber holding an OAuth token call administrator MCP tools, fixed in 3.4.9. Royal MCP's August advisory was its third authorization flaw of the year, after CVE-2026-40775 (opens in new tab) in June. MountDev's followed CVE-2026-15015 (opens in new tab) (CVSS 9.8) in July, where an unauthenticated visitor could self-register an OAuth client and obtain an administrator-bound token. A repeat is not proof of carelessness, but it tells you where to look before you install.
This guide is a buyer's checklist, not a scorecard: why the bug recurs, how to check any plugin for it, what to do if you run an affected version, and — in the one section about our own plugin — how Cowboy MCP gates its tools, limits included. For the broader question, start with is it safe to give AI access to WordPress?
Why does the same bug keep appearing?
Because an MCP tool is a new front door on a house that only guards the old ones. WordPress enforces permissions at the places it knows about — wp-admin screens, REST controllers, AJAX handlers — but an MCP tool is a plugin-defined function reached through the plugin's own endpoint, so the only capability check it gets is the one the plugin author writes. If the endpoint authenticates the caller and then trusts every tool equally, any account that can authenticate becomes an administrator for the duration of the call.
Three habits make that mistake easy:
- Authentication is mistaken for authorization. A valid session cookie, application password, or bearer token tells you who is calling, not what they may do. A subscriber is authenticated; a subscriber must not create administrators. Most of the 2026 advisories are exactly this gap, at the tool level.
- OAuth tokens become identities without roles. A bearer token from an OAuth connector is often stored with a client ID but not the approving user's capabilities, and rarely re-checked on each call. When the token is minted for a low-privilege account — or, as in CVE-2026-15015, for nobody at all — the handler cannot tell. The MCP specification's 2026-07-28 revision deprecates dynamic client registration in favour of client ID metadata documents (CIMD), largely because a public registration endpoint beside a weak authorization step kept failing.
- Tools have no declared blast radius. When every tool looks alike to the server, "list posts" and "delete user" pass the same gate. The protocol's
readOnlyHintanddestructiveHintannotations exist to fix that, and both Anthropic's and OpenAI's connector directories now require them on every tool. WordPress is heading the same way: WordPress 7.2, due 9 December 2026, splits core content abilities into separate query, create, update, and delete abilities so annotations can mark the destructive ones. None of this replaces a capability check, but it gives a server something to enforce.
The common thread: the check has to live in the tool dispatcher, on every call, against the actual caller — not at login, not at token issue, not in the tool list.
How do you check whether an MCP plugin re-checks permissions?
You can vet most plugins in an afternoon without reading all of their code. To check whether a WordPress MCP plugin re-checks permissions, search its advisory record, find the function that dispatches tool calls and confirm it consults capabilities or a per-credential scope on every call, then prove it with a subscriber account on a staging site.
- Search the record. Put the slug into NVD (opens in new tab), Wordfence Intelligence (opens in new tab), WPScan (opens in new tab), and Patchstack (opens in new tab). A fixed advisory with a fast patch is a good sign; a repeat in the same area is the thing to ask about.
- Ask who can authenticate at all. Can a subscriber, customer, or contributor obtain a credential the endpoint accepts? If yes, every tool must check capabilities. If credentials can only be issued by an administrator in wp-admin, the question becomes how narrowly each one can be scoped.
- Find the dispatcher. Every MCP plugin has one function that turns a
tools/callrequest into a PHP call. Look forcurrent_user_can, a scope or allow-list check, or a lookup of the tool's annotations before the handler runs. If it goes straight from "token is valid" tocall_user_func, the plugin is relying on each handler to check itself — so spot-check the ones that create users, write files, run SQL, or change options. - Check how OAuth tokens are bound. A token should record the approving user and be re-validated against that user's current role on every request, so removing an administrator role revokes their agent too. Consent should require an administrator, PKCE should be mandatory, and the redirect URI must match the registered one.
- Read the annotations. List the tools and confirm every write tool declares
readOnlyHint: falseand every delete, reset, or bulk overwrite declaresdestructiveHint: true. A plugin that omits them cannot offer a read-only credential that means anything. - Prove it on staging. Create a subscriber, obtain whatever credential a subscriber can get, and call an administrator tool — list users, update an option. The correct answer is a permission error. Repeat with a read-only credential and a write tool.
- Check the plugin's own protections. Can an agent change the plugin's settings, widen its own scope, or mint a new key through the API? Those should be write-protected from the endpoint even for an administrator credential, or an injected instruction can escalate itself.
The safety guide turns the same questions into a twelve-row evaluation sheet, and the comparison hub records which plugins declare annotations and OAuth support.
What should you do if you run one of the affected plugins?
Update, then assume the window was used. If you run an affected version, update to the fixed release immediately, revoke and reissue every OAuth token and application password the plugin accepted, and review users, options, and recent changes for anything a low-privilege account could not normally have done. Patching closes the door; it does not tell you whether anyone walked through it.
- Update first. If the fix has not reached the directory, disable the plugin or its endpoint until it does — the endpoint is reachable from the internet by design.
- Revoke credentials. Tokens minted before the fix were minted under the flawed check; reissue from a clean state.
- Audit the accounts. Look for new administrators, role changes, and edited email addresses; on multisite, check network users too. Open subscriber registration is the usual foothold.
- Diff the site. Compare options, active plugins, and recently modified files against a pre-disclosure backup, and read the plugin's audit log if it keeps one.
- Watch the second advisory. Where a project has repeat findings in one area, treat its next release as urgent.
How does Cowboy MCP gate its tools?
By credential, not by WordPress role — and the checks run in the dispatcher, on every call. Cowboy MCP has no role-based path into its endpoint: every request carries either an API key that only an administrator can issue in wp-admin, or an OAuth token that only exists because an administrator approved a consent screen, and each call then passes a per-credential scope check before anything else happens. The points below are verified against the plugin source at 1.6.6, limits included.
- Who can authenticate. API keys are created on the settings page, which requires the
manage_optionscapability; a subscriber or customer has no way to obtain one. The OAuth connector is off by default. When on, client registration is public as the specification requires, but authorization cannot complete without a logged-in administrator approving a consent screen on your own site, PKCE S256 is mandatory, and the redirect must match the registered one. Limit: the connector still uses dynamic client registration behind the consent gate; it does not yet implement client ID metadata documents. - Tokens stay bound to an administrator. Each OAuth token records the approving user, and every validation re-checks that the user still exists and still holds
manage_options; demote or delete the account and the token is revoked on the spot. Tokens are stored as SHA-256 digests; API keys are stored with WordPress's one-way password hash and compared against every key on each request, so the visible prefix can never act as a shortcut. - Scope is checked on every call. Each key and OAuth connection carries a scope — full, read-only, or a hand-picked tool list — and the dispatcher checks it after resolving the tool and before validating arguments, running a dry run, or applying safe mode, so an out-of-scope tool never leaks a preview. Discovery lists only in-scope tools, and the scope settings sit on a list of options that can never be written through the API, so a credential cannot widen itself. Per-credential scoping shipped in 1.6.2. Limit: a full-scope credential acts with administrator capabilities inside the guardrails — treat it like an administrator password.
- Annotations are a boundary, not decoration. All 168 tools declare
readOnlyHintanddestructiveHint, and abilities bridged in through the Abilities API inherit theirs. Read-only scope is enforced fromreadOnlyHint; safe mode, on by default, stops any tool withdestructiveHintuntil the call is resent withconfirm: true, and WP-CLI commands outside a short known-safe list get the same treatment. Every non-read-only tool accepts a dry run. - Capability checks inside handlers, where WordPress expects them. Tools that install, update, activate, or delete plugins and themes, manage users, upload or delete media, edit menus, and write SEO meta additionally call
current_user_canfor the matching capability before acting. Granting an administrator role, setting a password, or changing a privileged user's email requires power mode; a credential can never change its own role, password, or email, and the last administrator can be neither deleted nor demoted. Limit: because the request already runs as an administrator, these are belt-and-braces; the scope check is the gate. - The dangerous stuff stays locked. Without power mode the plugin blocks schema-destroying SQL (
DROP,TRUNCATE,ALTER), refuseseval,shell, and database-reset commands in WP-CLI — after tokenizing the command the way the shell would, so quoting tricks do not slip past — refuses writes intomu-plugins/(since 1.6.5), syntax-checks every PHP file before it lands, and rejects outbound requests to private addresses. Secret-looking options are refused to read-only resources and masked in output. Power mode is a wp-admin checkbox, and the plugin's own settings and keys stay hard-protected from API writes even when it is on. - Everything is recorded and reversible. Every call, error, and authentication event — including failed attempts and scope denials — goes to an audit log in your own database, credential-looking fields redacted first, pruned after 30 days. Journaled changes capture a before-state and roll back individually from the undo journal; database checkpoints run automatically before mutating WP-CLI commands and plugin or theme updates. Requests are capped at 120 a minute per credential by default, with a stricter per-IP throttle that also counts failed authentication. Limit: the journal keeps seven days by default, checkpoints restore tables rather than files, and the rate limiter is approximate under heavy concurrency.
That covers checklist steps 2 through 5 and 7. The security page walks through each guardrail with its edge cases, how undo works covers what happens when a change gets through anyway, and the plugin is open source on WordPress.org and GitHub, so every gate here can be read in the code rather than taken on trust.
FAQ
Has Cowboy MCP had a security vulnerability?
None published as of September 2026. Search the slug on NVD, Wordfence Intelligence, WPScan, and Patchstack rather than taking our word for it, and read the changelog: the project ships hardening proactively — tokenized WP-CLI blocklist matching and per-credential scoping in 1.6.2, power-mode gating for mu-plugins writes and PHP syntax checks in 1.6.5. A clean record is a snapshot, not a guarantee; the plugin is open source, and reports are welcome through the WordPress.org plugin security process.
How do I check whether an MCP plugin re-checks permissions?
Find the function that dispatches tools/call requests and look for a capability or scope check between "the token is valid" and the handler running — a current_user_can call, a per-credential allow-list, or a lookup of the tool's annotations. Then prove it on staging: create a subscriber, obtain whatever credential a subscriber can get, and call an administrator tool such as listing users. The correct answer is a permission error. Repeat with a read-only credential and a write tool.
Is an OAuth bearer token the same as an admin login?
Only if the plugin makes it so. A well-built connector records which user approved the token, requires that user to be an administrator at consent time, and re-checks their role on every request so the token dies when the role does. A weak one issues a token to any authenticated account, or to nobody, and then treats every token the same — several 2026 advisories were exactly that gap. Cowboy MCP binds each token to the approving administrator and fails closed if that account loses the role.
Do readOnlyHint and destructiveHint make a plugin safer?
Only when the server enforces them. As metadata they help a client decide whether to ask you before a call; as a gate they let a read-only credential refuse every write tool and safe mode stop every destructive one. A plugin can declare them and still trust every caller equally, so ask whether the annotations drive anything server-side. In Cowboy MCP, read-only scope and safe mode both key on them, which is why every tool declares both.
Should I turn off my MCP plugin until it is patched?
If you run an affected version and the fixed release is not yet available, yes — deactivate the plugin or disable its endpoint, because the endpoint is reachable from the internet by design. Once updated, revoke and reissue the credentials the plugin accepted, review users and options for changes a low-privilege account could not normally make, and read the audit log if the plugin keeps one. Patching closes the door; it does not tell you whether anyone used it.
Does self-hosting make this class of bug more or less likely?
Neither; it changes who can fix it and who sees the traffic. A self-hosted plugin puts the capability check in PHP you can read and update yourself, and keeps requests, credentials, and logs on your server. A hosted relay moves the check to infrastructure you cannot inspect and adds a second party to the data path. Either can get authorization wrong. The check that matters is the one in the tool dispatcher, and you can only audit it where you can read the code.