{"items":[{"id":"NVI-00011840","kind":"vulnerability","title":"ApostropheCMS: Page REST API authorization bypass","revision":1,"unknowns":["Customer inventory, deployment, reachability and exploitation have not been inspected."],"lifecycle":"active","identifiers":["GHSA-2j32-q6rx-h844","CVE-2026-113670"],"plain_summary":"GitHub lists this reviewed advisory for apostrophe. Published version ranges and source prerequisites are shown below; this is not an inspection of a visitor’s application.","review_status":"source_listed","control_topics":[],"public_actions":[{"summary":"Identify the exact component and deployed version, examine the linked publisher’s conditions, and retain evidence of any mitigation.","source_ids":["sr-4165b859e0f106f205b7f1e63fd6adaa"],"action_type":"investigate","limitations":"Confirm current vendor support, compatibility and deployment evidence. This report has not tested a fix in your system.","current_supported_target":null}],"schema_version":"1.1.0","source_metrics":[{"kind":"CVSS","as_of":"2026-10-20T18:13:09.000Z","value":"5.3 medium","meaning":"GitHub source severity; exploitability and local consequence require separate evidence.","source_id":"sr-4165b859e0f106f205b7f1e63fd6adaa"}],"why_it_matters":"Published affected context helps an owner decide what evidence to gather. This report has not examined your application.","related_sources":[{"id":"sr-4165b859e0f106f205b7f1e63fd6adaa","url":"https://github.com/advisories/GHSA-2j32-q6rx-h844","basis":"vendor_advisory","notes":"GitHub Advisory Database; CC-BY-4.0. Each advisory links its original attribution. Null normalizes fields.","title":"GHSA-2j32-q6rx-h844","publisher":"GitHub Advisory Database","observed_at":"2026-10-31T23:13:39.183Z"}],"affected_context":[{"certainty":"source_listed","source_ids":["sr-4165b859e0f106f205b7f1e63fd6adaa"],"technology":"apostrophe","known_exclusions":[],"conditions_summary":"**Summary**\nThe 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.\n\n**Details**\n`packages/apostrophe/modules/@apostrophecms/page/index.js`:\n- `getOne` (L456–465): `await self.publicApiCheckAsync(req); ... self.getRestQuery(req).permission(false).and(criteria)` — no `viewRole` threshold, no `visibility` filtering.\n- `all` handler (L318–395): `getRestQuery(req).permission(false)` (L384–385) walks every page type and returns the projection including `visibility`.\n- `publicApiCheckAsync` (L3044) only checks that `publicApiProjection` exists — it performs no authorization.\n- Correct control behaves differently: `piece-type/index.js:getOne` (L319–327) uses `getRestQuery(req)` without `.permission(false)` and enforces `viewRole`.\n\n**PoC**\n```\n# Anonymous (no session) — private, admin-only page:\ncurl \"http://localhost:3100/api/v1/@apostrophecms/page/d576242ve1dkzb12jiiabujd:en:published\"\n# → 200  {\"_id\":\"...:en:publish","public_affected_ranges":["< 4.33.0"]}],"null_published_at":"2026-11-01T01:03:56.609Z","source_updated_at":"2026-10-20T18:13:09.000Z","source_disclosed_at":"2026-10-20T18:13:08.000Z","is_synthetic_fixture":false,"null_last_reviewed_at":null,"public_change_summary":"First indexed by Null; source disclosure date is shown separately.","null_first_observed_at":"2026-10-31T23:13:39.183Z"}],"next_cursor":null,"snapshot_revision":"42594"}