Skip to content

actionDuplicate with deleteProvisionalDraft side-effect deletes peer drafts

Moderate
angrybrad published GHSA-2f55-h4xr-92p2 Aug 18, 2026

Package

composer craftcms/cms (Composer)

Affected versions

>= 5.0.0-RC1, < 5.10.11

Patched versions

5.10.11

Description

ElementsController::actionDuplicate() accepts a deleteProvisionalDraft request parameter. After successfully duplicating an element, if the source is a provisional draft and this flag is set, the controller calls deleteElement($element) directly, without performing a canDelete() authorization check. The duplicate operation itself is gated by canDuplicateAsDraft(), which, for Entry only, checks createEntries (no creatorId or deletePeerEntryDrafts requirement). A user with viewPeerEntryDrafts + createEntries (but no deletePeerEntryDrafts) can duplicate and delete another user’s provisional draft.

Impact

  • Victim loses unsaved provisional draft (auto-saved work in progress).
  • Attacker’s createEntries (content creation) escalates to cross-user delete capability.
  • A duplicate is created as the attacker’s own unpublished draft — the attacker gains the victim’s in-progress content.

Report ID: 1541

Severity

Moderate

CVE ID

No known CVE

Weaknesses

Missing Authorization

The product does not perform an authorization check when an actor attempts to access a resource or perform an action. Learn more on MITRE.