---
id: CVE-2026-50280
title: >-
  Craft CMS: Authorization bypass in `entries/move-to-section` via missing
  target-section save check
summary: >-
  Craft CMS: Authorization bypass in `entries/move-to-section` via missing
  target-section save check
severity: medium
cwe:
  - CWE-284
vendor: craftcms
product: craftcms/cms
ecosystem: composer
affected:
  - 'craftcms/cms >= 5.0.0-RC1, < 5.9.21'
patched:
  - craftcms/cms 5.9.21
published: '2026-07-02'
updated: '2026-07-02'
source: GHSA
sourceUrl: 'https://github.com/advisories/GHSA-43cq-c2gq-pfpw'
references:
  - url: 'https://github.com/craftcms/cms/security/advisories/GHSA-43cq-c2gq-pfpw'
  - url: 'https://nvd.nist.gov/vuln/detail/CVE-2026-50280'
  - url: >-
      https://github.com/craftcms/cms/commit/0a6b916f6367b0162b2eaf2366add67b45fa98ea
  - url: 'https://github.com/advisories/GHSA-43cq-c2gq-pfpw'
tags:
  - ghsa
  - composer
epss: 0.00404
epssPercentile: 0.34514
ingestedAt: '2026-07-02T19:41:50.969Z'
---

## Overview

### Summary

The `EntriesController::actionMoveToSection()` endpoint checks only whether the current user can view the destination section, but it does not require permission to save entries into that section. A low-privileged authenticated control-panel user who can move an entry out of its current section can therefore move that entry into a different section where they have read access but no write access.

### Details

The vulnerable route is implemented in [EntriesController.php](/D:/files/projects/cms-5.9.19/cms-5.9.19/src/controllers/EntriesController.php):465:

The destination check is only `viewEntries:$section->uid` . The source-entry gate is `Entry::canMove()`, which verifies whether the user can move the existing entry based on the source section:

This closes the exploit chain:

1. External source: authenticated CP request to `entries/move-to-section`.
2. Missing authorization check: destination section requires only `viewEntries`, not `saveEntries`.
3. Privileged sink: `moveEntryToSection()` rewrites `sectionId` and saves the entry into the unauthorized section.

Preconditions derived from the code:

1. The attacker is authenticated to the control panel.
2. Entry `345` is movable by the attacker from its current section.
3. The attacker can satisfy `viewEntries` on destination section `12`.
4. The attacker does not have `saveEntries:DESTINATION_UID`, which is the missing check that makes the bypass possible.

Result:

1. The controller accepts the request because `viewEntries:$section->uid` passes.
2. Each source entry passes `canMove()` based on source-section permissions.
3. `moveEntryToSection()` updates the entry’s `sectionId` and saves it.
4. The entry is now located in a section where the attacker did not have write permission.

### Impact

This breaks the intended section-level authorization model. A user with limited content permissions can inject or relocate content into a protected section, interfering with editorial boundaries, approval workflows, section-specific business logic, and content ownership expectations.

## Affected packages

- `craftcms/cms >= 5.0.0-RC1, < 5.9.21`

## Remediation

Upgrade to a patched release:

- `craftcms/cms 5.9.21`
