CVE-2026-58200 Overview
CVE-2026-58200 is a signature verification weakness [CWE-347] in the @jhb.software/payload-cloudinary-plugin, a Cloudinary integration for Payload CMS. Versions from 0.3.0 through 0.3.x expose the POST /api/cloudinary-generate-signature endpoint when clientUploads is enabled. The handler in cloudinary/src/getGenerateSignature.ts forwards attacker-controlled body.paramsToSign directly to cloudinary.utils.api_sign_request. No key allowlist, collection policy, timestamp freshness check, or folder enforcement is applied. Any authenticated Payload user can obtain a valid Cloudinary HMAC-SHA1 signature for arbitrary parameters. The issue is fixed in version 0.4.0.
Critical Impact
Authenticated users can turn the signature endpoint into a signing oracle, enabling asset overwrite, uploads to arbitrary folders, callbacks to attacker URLs, and cache invalidation on the Cloudinary account.
Affected Products
- @jhb.software/payload-cloudinary-plugin version 0.3.0
- @jhb.software/payload-cloudinary-plugin versions 0.3.x prior to 0.4.0
- Payload CMS deployments using this plugin with clientUploads enabled
Discovery Timeline
- 2026-09-15 - CVE-2026-58200 published to NVD
- 2026-09-15 - Last updated in NVD database
Technical Details for CVE-2026-58200
Vulnerability Analysis
The plugin exposes a server-side endpoint intended to sign a narrow set of upload parameters for browser-based Cloudinary uploads. In vulnerable releases, the handler accepts an arbitrary paramsToSign object from the authenticated request body and signs whatever is provided. Because the client-facing Cloudinary API key is by design visible to the browser, the missing server-side restrictions are the only barrier to unauthorized operations. A returned HMAC-SHA1 signature is sufficient to authorize Cloudinary API calls whose parameters were signed.
With control over paramsToSign, an attacker can request signatures for overwrite, type, notification_url, invalidate, folder, and public_id. This authorizes asset replacement at chosen public_id values, uploads outside the configured folder, changes to upload visibility, callbacks to attacker-selected URLs, and cache invalidation.
Root Cause
The endpoint lacks four controls: a parameter allowlist, a per-collection access check, a timestamp freshness window, and enforcement that the signed folder matches the configured folder. The default access function returned !!req.user, which authorizes any logged-in user regardless of their ability to create documents in the target collection.
Attack Vector
An authenticated Payload user sends a POST request to /api/cloudinary-generate-signature with a crafted paramsToSign body. The server returns a valid signature. The attacker then submits an upload directly to Cloudinary using that signature, the visible API key, and the malicious parameters.
// Patch excerpt: cloudinary/src/getGenerateSignature.ts
req: PayloadRequest
}) => boolean | Promise<boolean>
apiSecret: string
+ /** Slugs of the collections this plugin manages. Signatures may only be requested for these. */
+ collections: string[]
+ /** The configured upload folder. When set, the signed `folder` parameter must match it. */
+ folder?: string
}
-const defaultAccess: Args['access'] = ({ req }) => !!req.user
+/**
+ * By default a user may only request a signature if they are allowed to create
+ * documents in the target upload collection. Falling back to mere authentication
+ * would let any logged-in user mint signatures for collections they cannot upload to.
+ */
+const defaultAccess: Args['access'] = async ({ collectionSlug, req }) => {
+ const createAccess = req.payload?.collections?.[collectionSlug]?.config?.access?.create
+ if (!createAccess) {
+ return !!req.user
+ }
+ return Boolean(await createAccess({ data: {}, req }))
+}
+
+/** Reject signatures whose timestamp is too far from now to limit replay. */
+const maxTimestampSkewSeconds = 60 * 60
Source: GitHub Commit da232590
Detection Methods for CVE-2026-58200
Indicators of Compromise
- Cloudinary asset overwrites at existing public_id values not initiated by legitimate editors.
- Uploaded assets located outside the plugin's configured folder.
- Cloudinary notification_url callbacks reaching external domains not owned by the operator.
- Unexpected cache invalidation events on the Cloudinary account.
Detection Strategies
- Inspect application logs for POST /api/cloudinary-generate-signature requests containing parameters beyond timestamp, folder, and public_id.
- Correlate authenticated Payload sessions with the frequency of signature requests to surface abnormal signing activity.
- Compare Cloudinary upload metadata (folder, public_id, notification_url) against the plugin's configured folder allowlist.
Monitoring Recommendations
- Enable Cloudinary audit logs and alert on overwrite=true, invalidate=true, or non-empty notification_url values.
- Track the ratio of signature requests to actual upload completions for anomaly detection.
- Forward Payload CMS access and API logs into a central analytics platform for retention and correlation.
How to Mitigate CVE-2026-58200
Immediate Actions Required
- Upgrade @jhb.software/payload-cloudinary-plugin to version 0.4.0 or later.
- Rotate the Cloudinary API secret used by the plugin to invalidate any signatures obtained during exposure.
- Audit Cloudinary asset inventory for unexpected public_id overwrites and out-of-folder uploads.
- Review Payload user accounts and disable any that should not have upload rights.
Patch Information
The fix is delivered in GitHub Release cloudinary@0.4.0 via Pull Request #155 and commit da232590. The patched handler restricts signable parameters to an allowlist, enforces per-collection create access, checks timestamp freshness within a 60-minute window, and validates the signed folder against the configured folder. See the GitHub Security Advisory GHSA-h5x8-xp6m-x6q4 for advisory details.
Workarounds
- Disable clientUploads in the plugin configuration and route uploads through server-side handlers until patched.
- Provide a custom access function that verifies the caller has create permission on the target upload collection.
- Restrict authenticated user access to the /api/cloudinary-generate-signature route with a reverse proxy or web application firewall.
# Upgrade to the patched release
npm install @jhb.software/payload-cloudinary-plugin@0.4.0
# Verify installed version
npm ls @jhb.software/payload-cloudinary-plugin
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.