Skip to content

GHSA-qh45-9g5p-m2v4 CVE-2026-50283

Craft CMS: Unauthorized Deletion of Source Assets During File Replacement

Medium Packagist
Severity
0.0 / 10
Medium · CVSS 4.0
Exploit chance (EPSS)
0.36%
Chance of exploitation in the next 30 days. Higher than 30.29% of scored vulnerabilities.
Known exploited
No
Not in CISA's catalog
Weakness
CWE-639 Authorization Bypass Through User-Controlled Key
Fix
5.9.21
Upgrade craftcms/cms to this version or later

Description

We have identified an authorization issue in Craft CMS AssetsController::actionReplaceFile that can delete a source asset without source delete permission by supplying both assetId and sourceAssetId.

Description

Craft CMS’s craft\\controllers\\AssetsController::actionReplaceFile() supports replacing a target asset file using another existing asset as the source. The action loads:

  • $assetToReplace from assetId
  • $sourceAsset from sourceAssetId

It then enforces replace permissions using ($assetToReplace ?: $sourceAsset). When both IDs are provided, this expression resolves to the target asset so no permission check is performed against the source asset volume.

$this->requireVolumePermissionByAsset('replaceFiles', $assetToReplace ?: $sourceAsset);
$this->requirePeerVolumePermissionByAsset('replacePeerFiles', $assetToReplace ?: $sourceAsset);

src/controllers/AssetsController.php:L433-L434

In the branch where both assets are present, Craft copies the source file into the target and then deletes the source asset. There is no check for deleteAssets:<sourceVolumeUid> or deletePeerAssets:<sourceVolumeUid> for the source asset before deletion.

$assets->replaceAssetFile($assetToReplace, $tempPath, $assetToReplace->getFilename(), $sourceAsset->getMimeType());
Craft::$app->getElements()->deleteElement($sourceAsset);

src/controllers/AssetsController.php:L462-L463

Impact

An authenticated user who can replace files in one volume can delete assets in another volume where they do not have delete permission, as long as they can obtain a sourceAssetId. This can lead to unauthorized asset deletion, broken content references, and data loss.

Affected versions

Packagist

PackageVulnerableFixed in
craftcms/cms
>= 5.0.0-RC1, < 5.9.21
5.9.21
craftcms/cms
>= 4.0.0-RC1, < 4.17.14
4.17.14

How to fix

Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.

craftcms/cms Packagist → 5.9.21

composer
composer require craftcms/cms:^5.9.21

Severity breakdown

CVSS 4.0 0.0

CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:L/VA:L/SC:N/SI:N/SA:N

Attack vector
Network
Attack complexity
Low
Attack requirements
None
Privileges required
Low
User interaction
None
Confidentiality (vulnerable system)
None
Integrity (vulnerable system)
Low
Availability (vulnerable system)
Low
Confidentiality (subsequent systems)
None
Integrity (subsequent systems)
None
Availability (subsequent systems)
None

Weakness

CWE-639: Authorization Bypass Through User-Controlled Key

The system's authorization functionality does not prevent one user from gaining access to another user's data or record by modifying the key value identifying the data.

How to prevent it
  • Architecture and Design: For each and every data access, ensure that the user has sufficient privilege to access the record that is being requested.
  • Architecture and Design, Implementation: Make sure that the key that is used in the lookup of a specific user's record is not controllable externally by the user or that any tampering can be detected.
  • Architecture and Design: Use encryption in order to make it more difficult to guess other legitimate values of the key or associate a digital signature with the key so that the server can verify that there has been no tampering.

References

Timeline

  1. Published
  2. Last updated by the source
  3. Latest EPSS score
AdvisorySeverityWhy it's related
GHSA-7vrx-9684-xrf2
Craft CMS stores arbitrary content provided by unauthenticated users in session files
Medium Known exploited Also affects craftcms/cms
GHSA-f3gw-9ww9-jmc3
Craft CMS Allows Remote Code Execution
Critical Known exploited Also affects craftcms/cms
GHSA-x684-96hh-833x
Craft CMS has a potential RCE with a compromised security key
High Known exploited Also affects craftcms/cms
GHSA-2p6p-9rc9-62j9
Craft CMS has potential RCE when PHP `register_argc_argv` config setting is enabled
Critical Known exploited Also affects craftcms/cms
GHSA-wg23-69c2-gjc8
Craft CMS: Passkey login accepts replayed WebAuthn assertions
Medium Also affects craftcms/cms
GHSA-957r-qf9p-67xw
Craft CMS: Arbitrary file read via SplFileObject in non-sandboxed template contexts
Medium Also affects craftcms/cms
GHSA-596p-6jv8-775v
Craft CMS: Authenticated leak of secret environment variables
Medium Also affects craftcms/cms
GHSA-xxpx-f366-4xpq
Craft CMS: Authorization bypass: view-only Categories user can modify category structure via structures/move-element
Medium Also affects craftcms/cms
Is this in your code?

MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.

Check your repos with MergeHarbor