CVE-2026-105860 Overview
CVE-2026-105860 is a missing authorization vulnerability [CWE-862] in the Payload CMS @payloadcms/plugin-multi-tenant package. Payload is a free and open source headless content management system. The flaw resides in the default tenant array field access control, which permits an authenticated user to assign their own account to tenants they do not belong to. This breaks the tenant isolation model that multi-tenant deployments rely on to separate customer data and administrative scopes.
The issue affects @payloadcms/plugin-multi-tenant versions before 3.90.0 and canary versions before 4.0.0-canary.34. Deployments that already override the defaults with secured tenants.arrayFieldAccess.create and tenants.arrayFieldAccess.update functions are not affected.
Critical Impact
An authenticated user can self-assign membership to arbitrary tenants, bypassing tenant isolation and gaining unauthorized access to other tenants' data and administrative actions.
Affected Products
- Payload CMS @payloadcms/plugin-multi-tenant versions before 3.90.0
- Payload CMS @payloadcms/plugin-multi-tenant canary versions before 4.0.0-canary.34
- Payload deployments relying on default tenant array field access controls
Discovery Timeline
- 2026-10-06 - CVE-2026-105860 published to NVD
- 2026-10-06 - Last updated in NVD database
Technical Details for CVE-2026-105860
Vulnerability Analysis
The Payload multi-tenant plugin models tenant membership as an array field on the user document. Each entry links a user to a tenant and optionally a role. Access control for that array field is defined by tenants.arrayFieldAccess.create and tenants.arrayFieldAccess.update configuration hooks. When these are not supplied, the plugin falls back to permissive defaults that evaluate against the acting user without verifying that the target tenant assignment is one the user is allowed to make.
An authenticated user can issue an update to their own user record and append arbitrary tenant IDs to the tenants array. Because the default access functions do not reject assignments to tenants outside the user's current membership, the write succeeds. The user is then recognized as a member of the added tenant and can access that tenant's scoped data and administrative routes.
Root Cause
The root cause is missing authorization [CWE-862] in the default field-level access logic for the tenants array. The plugin's own validate function on the tenant relationship field was also skipped for draft, autosave, trash, and restore-version writes, which left alternate code paths unguarded even when validation existed.
Attack Vector
Exploitation requires a valid authenticated session with permission to update the user's own account. The attacker sends a standard update request against the users collection and includes additional tenant entries in the tenants array. No elevated privileges, user interaction, or special network position is required.
// Patch excerpt: packages/plugin-multi-tenant/src/fields/tenantField/index.ts
// fix: enforce tenant membership on write
import type { RelationshipFieldValidation, SingleRelationshipField } from 'payload'
import type { MultiTenantPluginConfig, RootTenantFieldConfigOverrides } from '../../types.js'
import { defaults } from '../../defaults.js'
import { getCollectionIDType } from '../../utilities/getCollectionIDType.js'
import { getTenantFromCookie } from '../../utilities/getTenantFromCookie.js'
import { getUserTenantIDs } from '../../utilities/getUserTenantIDs.js'
import { isValidTenantAssignment } from '../../utilities/isValidTenantAssignment.js'
const fieldValidation =
<ConfigType = unknown>({
tenantsArrayFieldName,
tenantsArrayTenantFieldName,
userHasAccessToAllTenants,
validateFunction,
}: {
tenantsArrayFieldName: string
tenantsArrayTenantFieldName: string
userHasAccessToAllTenants?: MultiTenantPluginConfig<ConfigType>['userHasAccessToAllTenants']
validateFunction?: RelationshipFieldValidation
}): RelationshipFieldValidation =>
async (value, options) => {
if (validateFunction) {
const result = await validateFunction(value, options)
if (result !== true) {
// ...
}
}
}
Source: GitHub Commit 19b5869
A new beforeValidate collection hook, addCollectionBeforeValidateHook, rejects writes that assign a tenant the acting user is not a member of. The hook runs on draft, autosave, trash, and restore-version writes, closing the paths that previously skipped field validation.
Detect Identity Attacks the Moment Authentication Fails
Singularity™ Identity surfaces credential misuse, lateral movement, and privilege escalation in real time, so you can contain the breach before it spreads.
Stop Identity AttacksDetection Methods for CVE-2026-105860
Indicators of Compromise
- User records whose tenants array contains tenant IDs that were not present in prior snapshots or audit logs.
- Update requests against the users collection where the request body includes tenant IDs the authenticated user did not previously belong to.
- Access to tenant-scoped resources by user accounts that have no legitimate business relationship with those tenants.
Detection Strategies
- Review Payload admin and API logs for PATCH or POST operations on the users collection that modify the tenants array.
- Correlate changes in the tenants array with the identity of the actor; self-modification of tenant membership by non-admin users is a strong signal.
- Query the database for users whose tenants array has grown recently and compare against expected provisioning workflows.
Monitoring Recommendations
- Enable write audit logging on the users collection and forward events to a centralized log store for analysis.
- Alert on any mutation of the tenants array performed by the same user whose record is being modified.
- Track the version of @payloadcms/plugin-multi-tenant in production builds to confirm patched releases are deployed.
How to Mitigate CVE-2026-105860
Immediate Actions Required
- Upgrade @payloadcms/plugin-multi-tenant to 3.90.0 or later, or canary 4.0.0-canary.34 or later.
- Audit all user records for unexpected tenant assignments created before the upgrade and revert unauthorized memberships.
- Rotate sessions and review activity logs for any tenant-scoped actions performed by users with suspicious tenant membership changes.
Patch Information
The fix is published in Payload CMS releases 3.90.0 and 4.0.0-canary.34. The patch adds an isValidTenantAssignment utility and a new addCollectionBeforeValidateHook that rejects writes assigning tenants the acting user is not a member of. Field validation is also made asynchronous so the membership check runs consistently. See the GitHub Security Advisory GHSA-p96c-xwx8-3cqj and GitHub Release v3.90.0 for full details.
Workarounds
- Override the plugin defaults by implementing custom tenants.arrayFieldAccess.create and tenants.arrayFieldAccess.update functions that explicitly verify the acting user is already a member of the target tenant.
- Restrict update access to the users collection so that non-administrative users cannot modify their own tenants array field.
# Upgrade to the patched version
npm install @payloadcms/plugin-multi-tenant@^3.90.0
# Or for canary builds
npm install @payloadcms/plugin-multi-tenant@4.0.0-canary.34
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

