CVE-2026-105867 Overview
CVE-2026-105867 is an access control vulnerability in Payload CMS, a free and open source headless content management system. The flaw affects the @payloadcms/storage-s3 package in versions prior to 3.90.0 and canary versions prior to 4.0.0-canary.34. An authenticated user can overwrite an existing S3 object belonging to another upload collection when client uploads are enabled for multiple collections sharing a bucket and useCompositePrefixes is false or unset. This bypasses the target collection's access controls and prior file validation. The issue is tracked under CWE-639: Authorization Bypass Through User-Controlled Key.
Critical Impact
Authenticated users can overwrite S3 objects owned by other upload collections, bypassing per-collection access controls and corrupting trusted file assets.
Affected Products
- Payload CMS @payloadcms/storage-s3 versions before 3.90.0
- Payload CMS @payloadcms/storage-s3 canary versions before 4.0.0-canary.34
- Deployments where multiple upload collections share one S3 bucket with client uploads enabled and useCompositePrefixes disabled
Discovery Timeline
- 2026-10-06 - CVE-2026-105867 published to NVD
- 2026-10-06 - Last updated in NVD database
Technical Details for CVE-2026-105867
Vulnerability Analysis
Payload CMS supports direct client-to-S3 uploads through signed URLs generated by the server. When several upload collections share a single bucket and useCompositePrefixes is unset, uploaded objects are keyed in a way that permits an authenticated user to request a signed URL whose object key collides with an existing object owned by a different collection. The S3 PutObject call succeeds and silently overwrites the prior object. This defeats access control checks that would normally gate writes to the targeted collection and ignores file validation applied during the original upload.
Root Cause
The root cause is an authorization bypass through a user-controlled object key. The signed URL generator did not constrain writes to prevent overwriting existing keys, and the shared-bucket layout allowed one collection's authenticated users to produce keys resolving into another collection's namespace. See the GitHub Security Advisory GHSA-7vg8-29qx-jgj8 for the maintainer analysis.
Attack Vector
An authenticated user requests a client-upload signed URL from the Payload API, supplying a filename and prefix that resolves to an object key already used by another collection. The signed PUT is executed directly against S3, replacing the existing object. Because validation is enforced at API ingestion time and not at the S3 layer, the overwritten object is not re-validated.
// Security patch in packages/storage-s3/src/generateSignedURL.ts
// Adds the S3 If-None-Match: '*' precondition so PutObject fails
// if the target key already exists.
Bucket: bucket,
ContentLength: filesizeLimit ? Math.min(filesize, filesizeLimit) : undefined,
ContentType: mimeType,
IfNoneMatch: '*',
Key: fileKey,
}),
{
// Source: https://github.com/payloadcms/payload/commit/2df8238fbf17edfce335c399b90bf524ba9906a2
// Companion patch in packages/storage-s3/src/client/S3ClientUploadHandler.ts
// Propagates server-provided headers (including If-None-Match) to the
// client-side PUT request.
const {
docPrefix: sanitizedDocPrefix,
filename: sanitizedFilename,
headers,
url,
} = (await response.json()) as {
docPrefix: string
filename?: string
headers: Record<string, string>
url: string
}
// Source: https://github.com/payloadcms/payload/commit/2df8238fbf17edfce335c399b90bf524ba9906a2
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-105867
Indicators of Compromise
- S3 PutObject events from authenticated Payload users where the object key maps to a collection the user does not own.
- Unexpected x-amz-version-id changes on objects in upload collections, indicating silent overwrites.
- Serving of files whose content type or hash no longer matches the metadata stored in the Payload database.
Detection Strategies
- Query S3 server access logs or CloudTrail data events for PutObject operations that target existing keys belonging to a different upload collection prefix.
- Compare S3 object ETags and sizes against the hash and size persisted in Payload's database to flag divergence.
- Alert on repeated signed-URL requests from a single authenticated principal that produce colliding keys across collections.
Monitoring Recommendations
- Enable S3 bucket versioning so overwritten objects can be identified and recovered.
- Enable CloudTrail S3 data events for buckets used by Payload client uploads and ship them to a centralized data lake.
- Monitor Payload application logs for signed URL generation requests and correlate with the resulting S3 PutObject calls.
How to Mitigate CVE-2026-105867
Immediate Actions Required
- Upgrade @payloadcms/storage-s3 to version 3.90.0 or canary 4.0.0-canary.34 or later.
- Audit S3 object versions for the affected buckets and restore prior versions of any object that was overwritten without authorization.
- Review authenticated user activity against upload endpoints during the exposure window.
Patch Information
The fix adds the S3 IfNoneMatch: '*' precondition to signed PutObject requests and forwards the required headers to the client-side upload handler. If the target key already exists, S3 rejects the request with a 412 Precondition Failed, preventing cross-collection overwrites. See the GitHub Release v3.90.0 and the GitHub Commit Details for the applied changes.
Workarounds
- Enable useCompositePrefixes on affected upload collections so each collection writes to a distinct key prefix.
- Use a separate S3 bucket per upload collection until the package can be upgraded.
- Disable client uploads and route uploads through the server, where Payload applies full access control and validation.
# Upgrade the storage-s3 package to the patched release
npm install @payloadcms/storage-s3@^3.90.0
# Or, if you track the canary channel
npm install @payloadcms/storage-s3@4.0.0-canary.34
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

