CVE-2026-50284: Craft CMS: Missing peer-permission check in `AssetsController::actionDeleteFolder` allows deletion of other users' assets

Published Jul 1, 2026
·
Updated

Summary

AssetsController::actionDeleteFolder() only requires the deleteAssets:<volume-uid> permission for the target folder. It never enforces deletePeerAssets:<volume-uid>, even though Assets::deleteFoldersByIds() cascades deletion to every descendant folder and every asset inside, regardless of who uploaded them. A low-privilege user who has been granted folder-management rights on a shared volume can therefore destroy assets uploaded by other users (peer assets), bypassing the per-asset peer-permission check that the sibling actionDeleteAsset endpoint correctly applies.

This is the same bug class that was just fixed in actionMoveFolder as GHSA-3w32-23wj-rxg3 (commit 05c2042, Apr 23 2026); the fix added requireVolumePermissionByFolder('deletePeerAssets', …) and savePeerAssets checks to the move endpoint but did not propagate to the delete-folder endpoint.

Details

src/controllers/AssetsController.php:552-569:

php public function actionDeleteFolder(): Response { $this->requireAcceptsJson(); $folderId = $this->request->getRequiredBodyParam('folderId');

$assets = Craft::$app->getAssets(); $folder = $assets->getFolderById($folderId);

if (!$folder) { throw new BadRequestHttpException('The folder cannot be found'); }

// Check if it's possible to delete objects in the target volume. $this->requireVolumePermissionByFolder('deleteAssets', $folder); // <-- only checks deleteAssets $assets->deleteFoldersByIds($folderId);

return $this->asSuccess(); }

requireVolumePermissionByFolder() (src/controllers/AssetsControllerTrait.php:75-88) only resolves to a single requirePermission('deleteAssets:<vol-uid>') call. The peer-equivalent helper (requirePeerVolumePermissionByAsset) is never invoked because there is no folder-level peer helper that iterates the folder's contents.

Assets::deleteFoldersByIds() (src/services/Assets.php:311-349) then enumerates the folder + every descendant folder, queries every asset under those IDs, and calls Craft::$app->getElements()->deleteElement($asset, true) directly:

php $assetQuery = Asset::find()->folderId($allFolderIds); $elementService = Craft::$app->getElements();

foreach (Db::each($assetQuery) as $asset) { $asset->keepFileOnDelete = !$deleteDir; $elementService->deleteElement($asset, true); }

This bypasses Asset::canDelete() (src/elements/Asset.php:1515-1536):

php public function canDelete(User $user): bool { if ($this->isFolder) { return false; } if (parent::canDelete($user)) { return true; } $volume = $this->getVolume(); if (Assets::isTempUploadFs($volume->getFs())) { return true; }

if ($this->uploaderId !== $user->id) { return $user->can("deletePeerAssets:$volume->uid"); // <-- never reached on cascade delete } return $user->can("deleteAssets:$volume->uid"); }

Compare to actionDeleteAsset (src/controllers/AssetsController.php:579-613), which correctly does:

php $this->requireVolumePermissionByAsset('deleteAssets', $asset); $this->requirePeerVolumePermissionByAsset('deletePeerAssets', $asset);

The fix that landed in 05c2042 for actionMoveFolder (src/controllers/AssetsController.php:733-765) added both savePeerAssets and deletePeerAssets requireVolumePermissionByFolder checks to mirror the per-asset pattern, but the same hardening was not applied to actionDeleteFolder or actionRenameFolder (which also calls deleteFoldersByIds indirectly through later logic).

The asymmetry between the two endpoints demonstrates the missing check.

Impact

- Integrity / availability of other users' assets on any volume where the attacker has deleteAssets but not deletePeerAssets: the attacker can permanently delete peer-owned files (and their parent folder structure) on the underlying filesystem, with no recovery via Craft's UI. - The Craft permission model explicitly distinguishes "delete your own assets" (deleteAssets) from "delete other users' assets" (deletePeerAssets) precisely so administrators can grant the former without the latter on shared volumes — this finding renders that distinction unenforceable for any user given folder-delete rights. - No information disclosure or remote code execution; impact is bounded to the affected volume's contents. - Does not require any non-default configuration: the affected endpoint is enabled by default and only requires that an administrator has split deleteAssets from deletePeerAssets (the documented, supported permission model).

Other sources

Craft CMS is a content management system (CMS). In versions 5.0.0-RC1 through 5.9.21 and 4.0.0-RC1 through 4.17.14, theAssetsController::actionDeleteFolder() only requires the deleteAssets:<volume-uid> permission for the target folder. It never enforces deletePeerAssets:<volume-uid>, even though Assets::deleteFoldersByIds() cascades deletion to every descendant folder and every asset inside, regardless of the uploader's assigned privileges. A low-privilege user who has been granted folder-management rights on a shared volume can therefore destroy assets uploaded by other users (peer assets), bypassing the per-asset peer-permission check that the sibling actionDeleteAsset endpoint correctly applies. This issue has been fixed in versions 4.17.15 and 5.9.22.

MITRE

Affected Software

4 affected componentsFixes available
Craft CMS Craft CMS>=5.0.0-RC1<=5.9.21, >=4.0.0-RC1<=4.17.14
Craft CMS Craft CMS<4.17.15, <5.9.22
composer/craftcms/cms>=4.0.0-RC1<4.17.15
4.17.15
composer/craftcms/cms>=5.0.0-RC1<5.9.22
5.9.22

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade composer/craftcms/cms to a version that resolves this vulnerability.

    Fixed in 4.17.15
  2. Upgrade

    Upgrade composer/craftcms/cms to a version that resolves this vulnerability.

    Fixed in 5.9.22
  3. Upgrade

    Upgrade to a fixed release to a version that resolves this vulnerability.

    Fixed in 4.17.15
  4. Upgrade

    Upgrade to a fixed release to a version that resolves this vulnerability.

    Fixed in 5.9.22
  5. Upgrade

    Upgrade to a fixed release to a version that resolves this vulnerability.

    Patch 05c2042
  6. Compensating control

    Review and restrict the folder-management rights granted to users on shared volumes: the affected endpoint requires only `deleteAssets:<volume-uid>` for the target folder, allowing deletion of peer-owned assets (descendants and contents) when `deletePeerAssets:<volume-uid>` is not also granted.

Event History

Jul 1, 2026
CVE Published
via MITRE·10:37 PM
Data Sourced
via MITRE·10:37 PM
DescriptionWeakness
Data Sourced
via NVD·11:16 PM
DescriptionSeverityWeakness
Jul 2, 2026
Advisory Published
via GitHub·06:49 PM
Data Sourced
via GitHub·06:49 PM
DescriptionWeaknessAffected Software
Free Weekly Intel

Don't miss critical vulnerabilities

Join thousands of security professionals who receive our weekly digest of trending CVEs, zero-days, and exploited vulnerabilities.

No spam. Unsubscribe anytime.

Frequently Asked Questions

1

What is the severity of CVE-2026-50284?

CVE-2026-50284 has a risk rating of 51, indicating a moderate severity level due to improper permission checks.

2

How do I fix CVE-2026-50284?

To fix CVE-2026-50284, update Craft CMS to the latest version that includes the necessary peer-permission checks for asset deletion.

3

What versions of Craft CMS are affected by CVE-2026-50284?

CVE-2026-50284 affects Craft CMS versions 5.0.0-RC1 through 5.9.21 and 4.0.0-RC1 through 4.17.14.

4

What does CVE-2026-50284 allow an attacker to do?

CVE-2026-50284 allows an attacker to delete other users' assets due to a missing peer-permission check in the deletion process.

5

Is CVE-2026-50284 related to data security?

Yes, CVE-2026-50284 poses a data security risk as it can lead to unauthorized asset deletions, impacting user data integrity.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203