{"id":"CVE-2026-50283","title":"Craft CMS: Unauthorized Deletion of Source Assets During File Replacement","summary":"Craft CMS: Unauthorized Deletion of Source Assets During File Replacement","severity":"medium","cwe":["CWE-639"],"vendor":"craftcms","product":"craftcms/cms","ecosystem":"composer","affected":["craftcms/cms >= 5.0.0-RC1, < 5.9.21","craftcms/cms >= 4.0.0-RC1, < 4.17.14"],"patched":["craftcms/cms 5.9.21","craftcms/cms 4.17.14"],"published":"2026-07-02","updated":"2026-07-02","source":"GHSA","sourceUrl":"https://github.com/advisories/GHSA-qh45-9g5p-m2v4","references":[{"url":"https://github.com/craftcms/cms/security/advisories/GHSA-qh45-9g5p-m2v4"},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-50283"},{"url":"https://github.com/craftcms/cms/commit/2c2579c7f1030872423f268d0c8b48377101961d"},{"url":"https://github.com/advisories/GHSA-qh45-9g5p-m2v4"}],"tags":["ghsa","composer"],"epss":0.00364,"epssPercentile":0.30281,"ingestedAt":"2026-07-02T19:41:50.967Z","slug":"CVE-2026-50283","body":"## Overview\n\nWe 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`.\n\n### Description\n\nCraft CMS’s `craft\\\\controllers\\\\AssetsController::actionReplaceFile()` supports replacing a target asset file using another existing asset as the source. The action loads:\n\n- `$assetToReplace` from `assetId`  \n- `$sourceAsset` from `sourceAssetId`\n\nIt 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.\n\n```php\n$this->requireVolumePermissionByAsset('replaceFiles', $assetToReplace ?: $sourceAsset);\n$this->requirePeerVolumePermissionByAsset('replacePeerFiles', $assetToReplace ?: $sourceAsset);\n```\n\n[*src/controllers/AssetsController.php:L433-L434*](https://github.com/craftcms/cms/blob/5.x/src/controllers/AssetsController.php#L433-L434)\n\nIn 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.\n\n```php\n$assets->replaceAssetFile($assetToReplace, $tempPath, $assetToReplace->getFilename(), $sourceAsset->getMimeType());\nCraft::$app->getElements()->deleteElement($sourceAsset);\n```\n\n[*src/controllers/AssetsController.php:L462-L463*](https://github.com/craftcms/cms/blob/5.x/src/controllers/AssetsController.php#L462-L463)\n\n### Impact\n\nAn 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.\n\n## Affected packages\n\n- `craftcms/cms >= 5.0.0-RC1, < 5.9.21`\n- `craftcms/cms >= 4.0.0-RC1, < 4.17.14`\n\n## Remediation\n\nUpgrade to a patched release:\n\n- `craftcms/cms 5.9.21`\n- `craftcms/cms 4.17.14`","depth":"sunlit","depthScore":28,"depthScoreParts":{"impact":27.5,"likelihood":0.1,"exploitation":0,"ransomware":0},"changes":[]}