# CVE-2026-63669: ApostropheCMS page move authorization bypass

Source: https://junglewise.ai/threats/cve-2026-63669-apostrophecms-page-move-authorization-bypass  
Publisher: Junglewise Threat Intelligence, https://junglewise.ai/threats  
Published: 2026-08-17. Updated: 2026-09-25  
License: CC BY 4.0 with a link back

CVE-2026-63669 · Severity: medium · CVSS 6.5 · Published 2026-08-17

ApostropheCMS is a headless Node.js CMS that manages pages with role-based access control, allowing projects to create admin-only or role-restricted page sections. A regression in the page-move logic bypasses destination authorization checks, allowing any authenticated editor to move pages into restricted subtrees they cannot create or edit, and to reorder protected sibling pages they have no permission to modify. This is an authorization-boundary violation that allows unauthorized restructuring of protected content, reachable directly via the public REST API.

Technologies: [Apostrophe CMS](https://junglewise.ai/threats/technologies/apostrophe-cms), [apostrophe (npm)](https://junglewise.ai/threats/technologies/apostrophe). Vendors: [Apostrophe](https://junglewise.ai/threats/vendors/apostrophe), [npm](https://junglewise.ai/threats/vendors/npm).

## Quick answers

**Is CVE-2026-63669 exploited in the wild?** No. Junglewise Threat Intelligence has no report of CVE-2026-63669 being exploited in the wild.

**How severe is CVE-2026-63669?** Medium severity, with a CVSS score of 6.5, published 17 August 2026.

**Which products and versions are affected?** Apostrophe CMS <= 4.31.0; apostrophe (npm) <= 4.31.0, SEMVER:introduced=0,fixed=4.32.0.

**Is there a fix for CVE-2026-63669?** Yes. apostrophe (npm): upgrade to 4.32.0 or later. Junglewise finds every place you run it, drafts the upgrade and applies it once you approve.

**How is CVE-2026-63669 attacked?** It is attacked over the network, in a software library.

**Am I affected by CVE-2026-63669?** Check whether you run Apostrophe CMS or apostrophe (npm) at an affected version. Junglewise does that check for you around the clock: connect your code, cloud and domains, and it matches new vulnerabilities like this one against what you actually run and tells you when one reaches you.

## How to fix

- apostrophe (npm): upgrade to 4.32.0 or later

  ```sh
  npm install apostrophe@4.32.0
  ```


## Technical details

The vulnerability is a logic error in the `move()` guard in `packages/apostrophe/modules/@apostrophecms/page/index.js`. The guard is intended to enforce that pages can only be moved into a parent if the actor has `create` rights on that parent. However, a regression introduced a four-clause AND condition: `(oldParent._id !== parent._id) && (parent.type !== '@apostrophecms/archive-page') && (!parent._create) && (oldParent.type === '@apostrophecms/archive-page' && !parent._edit)`. Because the final clause gates the entire check on `oldParent` being the archive, the condition is false for all ordinary moves (where the source page's parent is not the archive), so the `!parent._create` check is never evaluated. The only enforcement that survives is `moved._edit` (can the actor edit the page being moved), which editors legitimately hold for their own pages. The destination target is fetched with `.permission(false)`, so the broken guard is the sole authorization boundary. An attacker can issue a `PATCH /api/v1/@apostrophecms/page/<pageId>` with attacker-controlled `_targetId` and `_position` fields to move a page under a restricted parent and trigger an unguarded `updateMany` that re-ranks the restricted parent's children. Patch available in version 4.32.0.

## Affected products

- ApostropheCMS apostrophe <= 4.31.0

## Identifiers

- CVE-2026-63669
- GHSA-wr5r-wqp2-x4fh

## Timeline

- 2026-09-03: disclosed: Public disclosure via GitHub Advisory Database
- 2026-08-12: patched: Fix released in version 4.32.0

## References

- [https://api.github.com/users/5ud0er](https://api.github.com/users/5ud0er)
- [https://github.com/5ud0er](https://github.com/5ud0er)
- [https://api.github.com/users/5ud0er/gists%7B/gist_id%7D](https://api.github.com/users/5ud0er/gists%7B/gist_id%7D)
- [https://api.github.com/users/5ud0er/repos](https://api.github.com/users/5ud0er/repos)
- [https://avatars.githubusercontent.com/u/88728909?v=4](https://avatars.githubusercontent.com/u/88728909?v=4)
- [https://api.github.com/users/5ud0er/events%7B/privacy%7D](https://api.github.com/users/5ud0er/events%7B/privacy%7D)

## Related threats

- [ApostropheCMS unauthenticated file upload in import routes](https://junglewise.ai/threats/cve-2026-113711-apostrophecms-is-an-open-source-node-js-content-management)
- [ApostropheCMS password-change endpoint lacks attempt throttling](https://junglewise.ai/threats/cve-2026-113710-apostrophecms-no-attempt-throttling-on-authenticated-password)
- [ApostropheCMS page REST API authorization bypass](https://junglewise.ai/threats/cve-2026-113670-apostrophecms-page-rest-api-authorization-bypass)
- [ApostropheCMS cross-domain session token in URL confers session takeover](https://junglewise.ai/threats/cve-2026-113669-apostrophecms-cross-domain-session-token-in-url-confers-session)
- [ApostropheCMS REST route authorization bypass in locales endpoint](https://junglewise.ai/threats/cve-2026-113668-apostrophecms-id-locales-rest-route-omits-the-public-api)
