VYPR
Moderate severityNVD Advisory· Published Mar 24, 2026· Updated Mar 25, 2026

Craft CMS: Authorization bypass in "entries/move-to-section" allows control panel user to move entries without section permissions

CVE-2026-33162

Description

Craft CMS is a content management system (CMS). From version 5.3.0 to before version 5.9.14, an authenticated control panel user with only accessCp can move entries across sections via POST /actions/entries/move-to-section, even when they do not have saveEntries:{sectionUid} permission for either source or destination section. This issue has been patched in version 5.9.14.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
craftcms/cmsPackagist
>= 5.3.0, < 5.9.145.9.14

Affected products

1

Patches

1
3c1ab1c4445d

Fixed GHSA-f582-6gf6-gx4g

https://github.com/craftcms/cmsbrandonkellyFeb 25, 2026via ghsa
3 files changed · +24 7
  • CHANGELOG.md+2 0 modified
    @@ -3,7 +3,9 @@
     ## Unreleased
     
     - The `PDO::MYSQL_ATTR_MULTI_STATEMENTS` attribute is no longer set by default for database connections. ([#18474](https://github.com/craftcms/cms/issues/18474))
    +- Added `craft\elements\Entry::canMove()`.
     - Fixed a bug where element selector modals weren’t showing any results if they were limited to sources that only exist for a different site than the active one. ([#18478](https://github.com/craftcms/cms/issues/18478))
    +- Fixed a [moderate-severity](https://github.com/craftcms/cms/security/policy#severity--remediation) authorization bypass vulnerability. (GHSA-f582-6gf6-gx4g)
     
     ## 5.9.13 - 2026-02-24
     
    
  • src/controllers/EntriesController.php+15 4 modified
    @@ -463,26 +463,37 @@ public function actionMoveToSection(): Response
             $this->requireCpRequest();
     
             $sectionId = $this->request->getRequiredParam('sectionId');
    +        $entryIds = $this->request->getRequiredParam('entryIds');
    +        if (empty($entryIds)) {
    +            throw new BadRequestHttpException('entryIds cannot be empty.');
    +        }
    +
             $section = Craft::$app->getEntries()->getSectionById($sectionId);
             if (!$section) {
                 throw new BadRequestHttpException('Cannot find the section to move the entries to.');
             }
     
    -        $entryIds = $this->request->getRequiredParam('entryIds');
    -        if (empty($entryIds)) {
    -            throw new BadRequestHttpException('entryIds cannot be empty.');
    -        }
    +        $this->requirePermission("viewEntries:$section->uid");
    +
    +        /** @var Entry[] $entries */
             $entries = Entry::find()
                 ->id($entryIds)
                 ->status(null)
                 ->drafts(null)
                 ->site('*')
                 ->unique()
                 ->all();
    +
             if (empty($entries)) {
                 throw new BadRequestHttpException('Cannot find the entries to move to the new section.');
             }
     
    +        foreach ($entries as $entry) {
    +            if (!$entry->canMove()) {
    +                throw new ForbiddenHttpException('User is not authorized to perform this action.');
    +            }
    +        }
    +
             $errors = [];
             foreach ($entries as $entry) {
                 try {
    
  • src/elements/Entry.php+7 3 modified
    @@ -2497,15 +2497,19 @@ protected function htmlAttributes(string $context): array
             return [
                 'data' => [
                     'entry-type-id' => $this->getType()->id,
    -                'movable' => $this->_canMove(),
    +                'movable' => $this->canMove(),
                 ],
             ];
         }
     
         /**
    -     * Returns whether the given user is authorized to move this entry.
    +     * Returns whether the given user is authorized to move this entry to a different section.
    +     *
    +     * @param User|null $user
    +     * @return bool
    +     * @since 5.9.14
          */
    -    private function _canMove(?User $user = null): bool
    +    public function canMove(?User $user = null): bool
         {
             if (!$user) {
                 $user = Craft::$app->getUser()->getIdentity();
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.