mediumCVSS 6.5Vulnerability

CVE-2026-63669

## Summary ApostropheCMS enforces per-type authorization on pages: a page type may declare `editRole` / `publishRole` (and the core `@apostrophecms/archive-page` does), so a project can have page-type subtrees that only higher-privileged roles are allowed to create or edit within. The `move()` operation is supposed to enforce that a page may only be moved *into* a parent the actor has **create** rights over — this is the same boundary the page-insert route enforces (the insert target is fetched with `.permission('create')`). A regression in the move authorization guard silently disabled that destination check for every normal move. The guard now reads `(oldParent._id !== parent._id) && (parent.type !== '@apostrophecms/archive-page') && (!parent._create) && (oldParent.type === '@apostrophecms/archive-page' && !parent._edit)`. Because the final `&&` clause requires `oldParent.type === '@apostrophecms/archive-page'`, the whole conjunction can only be true while restoring a page *out of the archive*. For any ordinary move (the source page's old parent is a normal page), that clause is `false`, the entire condition is `false`, and `!parent._create` is never evaluated. The only surviving gate in the whole path is `moved._edit` — i.e. "can the actor edit the page being moved", which a low-privileged editor legitimately holds for their own ordinary pages. The result is that any authenticated user who can edit at least one page can relocate that page **under a parent of a restricted type they have no create/edit rights over**, and in doing so trigger an unauthenticated, unchecked `updateMany` that re-ranks the restricted parent's existing children (documents the actor cannot edit). This is reachable directly from the documented `PATCH`/`PUT /api/v1/@apostrophecms/page/:_id` REST routes via the attacker-controlled `_targetId` / `_position` body fields. ## Affected code (4.31.0) The broken guard in `move()` — `packages/apostrophe/modules/@apostrophecms/page/index.js`: ```

Properties

severity
medium
summary
ApostropheCMS: Missing destination-parent authorization in page `move()` allows a low-privileged editor to move and re-rank pages inside a restricted subtree
epss_score
0.00221
cvss_score
6.5
ghsa_published
2026-09-03T20:05:08Z
source_url
https://github.com/advisories/GHSA-wr5r-wqp2-x4fh
ghsa_updated
2026-09-03T20:05:10Z
ghsa_id
GHSA-wr5r-wqp2-x4fh
cve_id
CVE-2026-63669
cvss_vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N
is_ghsa_only
false
epss_percentile
0.12461

Related Entities (6)

ENRICHED_BY (1)

[Source]FIRST EPSS

VULNERABLE_TO (1)

[Software]npm/apostrophe

AFFECTS (1)

[Software]npm/apostrophe

HAS_WEAKNESS (2)

[Weakness]Authorization Bypass Through User-Controlled Key
[Weakness]Missing Authorization

REPORTED_BY (1)

[Source]GitHub Advisory Database

Explore deeper with Ninja Signal's threat intelligence graph

CVE-2026-63669 (CVSS 6.5) — Ninja Signal Threat Intelligence | Ninja Signal