Oct 7, 2026·6 min read·2 visits
Unauthenticated remote attackers can pollute the global object prototype in Payload CMS to bypass access controls and execute arbitrary code on the server.
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.
The @payloadcms/plugin-import-export plugin provides essential administrative capabilities to Payload CMS, a headless content management system built on Next.js. Specifically, the plugin manages collection data exports and imports, allowing administrators to transfer content via formats like JSON or CSV. To achieve this, it maps user-specified field arrays to configuration objects and queries.
Because the plugin does not properly sanitize or filter the user-supplied field paths, it exposes a critical entry point for prototype pollution. Unauthenticated attackers can submit custom paths containing special object properties such as proto. This lack of validation represents a significant implementation flaw in the processing engine.
This vulnerability is tracked under the identifier CVE-2026-105844 with a high CVSS rating. It falls under the category of CWE-1321, which designates improperly controlled modification of object prototype attributes. The ultimate impact of successful exploitation is arbitrary code execution, presenting a severe risk to affected deployments.
The root cause of this flaw lies in the path-parsing logic implemented within the plugin's utility files. Functions like setNestedValue are designed to dynamically traverse and set values on objects based on split dot-notation paths. When processing paths, the application splits the input string by periods and recursively accesses the corresponding keys on the current target object.
During traversal, the function dynamically creates intermediate empty objects when a given path segment is not found. However, the routine lacks checks to prevent traversal of the built-in JavaScript proto accessor. Consequently, if the path contains proto, the reference pointer is successfully redirected to the global Object.prototype structure.
Any subsequent key-value assignment is then applied directly to Object.prototype rather than a local, isolated property. Because all plain JavaScript objects inherit from this prototype, any properties added or altered during this process propagate globally. This mutation of basic object properties undermines the runtime environment's reliability and security controls.
In the vulnerable codebase, the setNestedValue function evaluates each split segment of the user-provided path sequentially. It makes no distinction between ordinary data fields and critical system properties. The lack of input validation enables attackers to pass prototype-polluting paths into the traversal loop directly.
// Vulnerable setNestedValue loop
for (let i = 0; i < parts.length; i++) {
const part = parts[i]
const isLast = i === parts.length - 1
const isIndex = !Number.isNaN(Number(part))
if (!isIndex) {
const currentObj = current as Record<string, unknown>
if (isLast) {
if (typeof part === 'string') {
currentObj[part] = value // Vulnerable assignment to prototype
}
} else {
if (typeof currentObj[part as string] !== 'object' || currentObj[part as string] === null) {
currentObj[part as string] = {}
}
current = currentObj[part as string]
}
}
}The remediated code implements strict filtering prior to executing any traversal or assignment. A newly added utility function, hasUnsupportedFieldPathSegment, validates that no path segments match proto, constructor, or prototype. Furthermore, the functions now utilize Object.create(null) to guarantee prototype-free container structures, eliminating the default prototype chain lookup entirely.
// Safe setNestedValue implementation
export const setNestedValue = (
obj: Record<string, unknown>,
path: string,
value: unknown,
source?: Record<string, unknown>,
): void => {
const parts = path.split('.')
if (hasUnsupportedFieldPathSegment(parts)) {
throw new APIError('Invalid field path.', 400, null, true)
}
// Traversal loop continues safely...
}Exploitation of CVE-2026-105844 requires that the target application has the @payloadcms/plugin-import-export plugin configured and enabled. An unauthenticated attacker can initiate the compromise by issuing a single, crafted HTTP POST request. The request targets the /api/exports/export-preview endpoint and includes a polluted payload inside the fields parameter.
The target application processes the fields array to generate an export layout, calling the vulnerable setNestedValue routine. By submitting a path like proto.overrideAccess with a value of true, the attacker modifies the base object prototype of the entire runtime. As a result, subsequent empty options objects checked by Payload's internal access engine will automatically return true for overrideAccess.
This behavior effectively disables access control verification across the entire application instance. Unauthenticated requests are then processed as though they possess full administrative privileges. From this position, attackers can execute sensitive operations, manipulate database entries, or leverage system utilities to gain remote code execution.
The overall impact of this vulnerability is critical, presenting a severe risk to any internet-exposed Payload CMS instance. Because the endpoint does not require authentication, attackers can execute this exploit from arbitrary network positions. No prior access credentials or system privileges are necessary to perform the attack successfully.
By leveraging the prototype pollution vulnerability, the attacker completely subverts the application's authorization and authentication layers. This subversion grants access to restricted administrative capabilities, including database operations, user management, and system tool execution. Consequently, the confidentiality, integrity, and availability of all hosted data are fully compromised.
Furthermore, the ability to control properties on the global Object.prototype opens multiple paths to remote code execution. Attackers can pollute options passed to system execution utilities such as child_process.spawn, or inject malicious options into templating engines. The resulting complete system compromise enables unauthorized actors to execute arbitrary operating system commands.
The complete resolution of this vulnerability is achieved by updating the Payload CMS packages to their respective non-vulnerable versions. Deployments on the 3.x release track must be updated to version 3.88.0 or higher. Deployments utilizing the canary pre-release track must be updated to version 4.0.0-canary.27 or higher.
If immediate software updates are impossible, temporary mitigation strategies must be applied. Web Application Firewalls (WAFs) should be configured with deep packet inspection rules to identify and drop requests targeting /exports/export-preview that contain proto, constructor, or prototype strings. These filters help reduce the immediate threat surface.
Additionally, access controls should be enforced at the reverse proxy level to limit exposure of administrative and preview endpoints to trusted networks only. While these workarounds reduce the likelihood of exploitation, they do not resolve the underlying vulnerability in the application logic. Complete security compliance can only be established by applying the vendor-supplied updates.
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Payload CMS (@payloadcms/plugin-import-export) Payload CMS | >= 3.0.0, < 3.88.0 | 3.88.0 |
Payload CMS (canary) Payload CMS | < 4.0.0-canary.27 | 4.0.0-canary.27 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-1321 |
| Attack Vector | Network (AV:N) |
| CVSS Score | 9.3 (Critical) |
| EPSS Score | N/A |
| Impact | Remote Code Execution (RCE) / Privilege Escalation |
| Exploit Status | Proof of Concept (PoC) documented |
| KEV Status | Not listed |
Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')
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.
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.
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.