Skip to main content
Vulnerability Database/CVE-2026-105867

CVE-2026-105867: Payload CMS S3 Storage Auth Bypass Flaw

CVE-2026-105867 is an authentication bypass flaw in Payload CMS S3 storage plugin that allows authenticated users to overwrite S3 objects across collections. This post covers technical details, affected versions, and mitigation.

Published:

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.

typescript
// 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
typescript
// 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 Attacks

Detection 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.
bash
# 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.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.