Oct 7, 2026·5 min read·6 visits
A missing authorization check in @payloadcms/plugin-mcp allows authenticated low-privilege users to generate MCP API keys mapped to administrative accounts, resulting in privilege escalation and full account takeover.
CVE-2026-105806 is an improper access control vulnerability within the Model Context Protocol (MCP) plugin for Payload CMS. Authenticated users with low privileges can manipulate API key creation and mapping to associate keys with arbitrary users, including administrators. This allows total session takeovers and privilege escalation via MCP-authenticated API requests.
The Model Context Protocol (MCP) plugin for Payload CMS integrates LLM-based agent capabilities with the database layer of Payload CMS. It exposes a specific collection, payload-mcp-api-keys, which manages authentication tokens for MCP clients.\n\nUnder normal operations, these API keys associate client sessions with specific CMS user identities, granting them the capability to run automated actions inside Payload CMS. The security model relies on these keys executing precisely within the permission scope of their linked user.\n\nHowever, prior to version 3.88.0, the collection defining these keys omitted collection-level and field-level access controls. This omission allowed any authenticated user to interact with the database records of other users or generate new keys mapped directly to high-privilege administrators.
The root cause of CVE-2026-105806 is the absence of authorization checks on the payload-mcp-api-keys collection and its associated relationship fields.\n\nIn Payload CMS, database collections without explicit access properties default to allowing read, write, and update permissions for any authenticated user. Because the plugin defined the payload-mcp-api-keys collection without restriction, any authenticated entity could submit requests to retrieve or alter API keys.\n\nFurthermore, the user relationship field lacked restrictions, allowing client-supplied input to directly map the owner ID during creation or modification operations. This combination allowed an attacker to bypass user boundaries, associating their generated API key with an administrative identifier.
Prior to the patch, the payload-mcp-api-keys collection did not implement restrictive access control hooks. The user field allowed direct user-supplied mutations.\n\nmermaid\ngraph LR\n A["Attacker (Low Privilege)"] -->|1. POST /api/payload-mcp-api-keys| B["Payload CMS API"]\n B -->|2. Stores user: admin-id| C[("Database")]\n C -->|3. Issues Administrative Token| A\n\n\nThe patch in commit 025581d8c5ed836039ad85397288a30f0d3c11c1 mitigated this by adding strict validation checks. Let us examine the modifications introduced in packages/plugin-mcp/src/collections/createApiKeysCollection.ts:\n\nts\n const isAuthenticated = ({ req }: { req: PayloadRequest }): boolean =>\n Boolean(req.user && req.user.collection === userCollection)\n\n const restrictToOwnKeys = ({ req }: { req: PayloadRequest }): boolean | Where =>\n req.user && req.user.collection === userCollection ? { user: { equals: req.user.id } } : false\n\n return {\n slug: 'payload-mcp-api-keys',\n access: {\n create: isAuthenticated,\n delete: restrictToOwnKeys,\n read: restrictToOwnKeys,\n unlock: restrictToOwnKeys,\n update: restrictToOwnKeys,\n },\n\n\nAdditionally, the user field access controls were set to false for direct creation and updates from client inputs, forcing the use of a server-side default value hook:\n\nts\n {\n name: 'user',\n type: 'relationship',\n access: {\n create: () => false,\n update: () => false,\n },\n defaultValue: ({ req }: { req: PayloadRequest }) =>\n req.user && req.user.collection === userCollection ? req.user.id : undefined,\n relationTo: userCollection as CollectionSlug,\n required: true,\n },\n\n\nThis architecture guarantees that the database always resolves the API key's owner directly from the verified server-side session variable (req.user.id), eliminating the potential for identity spoofing.
An attacker must first authenticate to Payload CMS using a legitimate, low-privilege account. No special elevated roles or permissions are required to launch this attack.\n\nThe attacker then requests a list of administrators or obtains an administrator ID via standard enumeration methods, which is a common pattern in multi-user content management systems.\n\nNext, the attacker submits an API key creation payload to the MCP endpoint. By explicitly passing the targeted administrative user's ID within the user relationship field, the attacker registers a new API key.\n\nWhen the system processes subsequent requests presenting this API key, the authentication layer maps the session to the target administrative user. The attacker can then perform administrative actions and execute system tools with full privileges.
The impact of CVE-2026-105806 is rated as High, with a CVSS v4.0 score of 8.6. Exploitation allows complete privilege escalation and full account takeover.\n\nBecause the MCP plugin interacts directly with the database layer, an administrative token gives the attacker full write and read capabilities across all collections. This includes accessing sensitive proprietary data, user credentials, and configuration files.\n\nIf the CMS manages critical integration systems or runs system-level tasks, the attacker could leverage the MCP engine to execute arbitrary code. The lack of operational complexity makes this a severe risk for enterprise installations running vulnerable versions of the plugin.
The primary remediation step is to upgrade @payloadcms/plugin-mcp to version 3.88.0 or higher, which secures the default collection properties.\n\nIf upgrading is not immediately possible, administrators must restrict access to the payload-mcp-api-keys collection manually or disable the MCP plugin entirely. Deploying custom access control hooks on the collection schema can temporarily mitigate the vulnerability.\n\nFor custom workflows that require cross-user management of API keys by administrators, developers must use the overrideApiKeyCollection hook to safely enforce access control logic. Below is a secure configuration demonstrating how to limit management privileges strictly to administrative users:\n\nts\nimport type { PayloadRequest } from 'payload'\nimport { mcpPlugin } from '@payloadcms/plugin-mcp'\n\nconst isAdmin = ({ req }: { req: PayloadRequest }) =>\n Boolean(\n req.user &&\n req.user.collection === 'users' &&\n 'role' in req.user &&\n req.user.role === 'admin',\n )\n\nmcpPlugin({\n overrideApiKeyCollection: (collection) => {\n collection.access = {\n create: isAdmin,\n delete: isAdmin,\n read: isAdmin,\n unlock: isAdmin,\n update: isAdmin,\n }\n collection.fields = collection.fields.map((field) =>\n 'name' in field && field.name === 'user'\n ? { ...field, access: { create: isAdmin, update: isAdmin } }\n : field,\n )\n return collection\n },\n})\n
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
@payloadcms/plugin-mcp Payload CMS | >= 3.61.0, < 3.88.0 | 3.88.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-862 |
| Attack Vector | Network |
| CVSS v4.0 | 8.6 |
| Exploit Status | Unproven / None |
| KEV Status | Not Listed |
The software does not perform an authorization check when an actor attempts to access a resource or perform an action.
A critical SQL Injection and access control bypass vulnerability was identified in Payload CMS database adapters (SQLite and PostgreSQL using Drizzle ORM internally). The vulnerability arises from case-sensitive logical operator checks during path validation and unvalidated sort queries. This allows remote attackers to bypass access control rules, execute unauthorized queries, and retrieve sensitive data through blind SQL injection side channels.
A critical prototype pollution vulnerability in the import-export plugin of Payload CMS allows unauthenticated remote attackers to bypass access controls and achieve remote code execution.
An access control vulnerability in `@payloadcms/plugin-stripe` allows authenticated low-privilege users to bypass authorization boundaries and execute arbitrary, highly privileged operations on the connected Stripe platform via an exposed REST proxy.
A critical access control bypass vulnerability (CVE-2026-105851) in Payload CMS allows authenticated users to bypass field-level access controls during document duplication. By duplicating high-privilege documents, such as administrator accounts, standard users can inherit sensitive fields (e.g., role configurations or API keys), leading to privilege escalation.
CVE-2026-105853 is a high-severity information disclosure vulnerability in Payload CMS that affects authentication-enabled collections. In vulnerable versions, the application fails to properly serialize and sanitize user documents during token refresh and password reset operations. This deficiency leaks hidden and read-restricted fields to unauthorized actors. Additionally, a logical flaw in token refresh validation allows low-privileged users to cross collection boundaries, exposing sensitive configuration details and administrative metadata.
An authorization bypass vulnerability in Payload CMS enables unauthenticated attackers to query and infer the existence of restricted documents via nested relationship queries on public collections. This cross-document contamination flaw affects both MongoDB and Drizzle SQL database adapters, allowing unauthorized reads of relationship metadata.