---
id: CVE-2026-112952
aliases:
  - GHSA-f66c-mpj2-3r8h
title: >-
  ApostropheCMS: POST /api/v1/@apostrophecms/doc/slugTaken discloses existence
  of private/admin-only content to any authenticated user
summary: >-
  ApostropheCMS: POST /api/v1/@apostrophecms/doc/slugTaken discloses existence
  of private/admin-only content to any authenticated user
severity: medium
cvss: 4.3
cwe:
  - CWE-200
vendor: apostrophe
product: apostrophe
ecosystem: npm
affected:
  - apostrophe < 4.34.0
patched:
  - apostrophe 4.34.0
published: '2026-10-21'
updated: '2026-10-21'
sourceUpdated: '2026-10-21T17:17:02Z'
source: GHSA
sourceUrl: 'https://github.com/advisories/GHSA-f66c-mpj2-3r8h'
references:
  - url: >-
      https://github.com/apostrophecms/apostrophe/security/advisories/GHSA-f66c-mpj2-3r8h
  - url: 'https://nvd.nist.gov/vuln/detail/CVE-2026-112952'
  - url: >-
      https://github.com/apostrophecms/apostrophe/commit/06e4b377f3c360f9e89c32dccd7e505ad5ddf498
  - url: >-
      https://github.com/apostrophecms/apostrophe/commit/40b989b1a9dd23d30029b8ce7668634265cfe5ea
  - url: 'https://github.com/apostrophecms/apostrophe/releases/tag/apostrophe@4.34.0'
  - url: 'https://github.com/advisories/GHSA-f66c-mpj2-3r8h'
tags:
  - ghsa
  - npm
  - cve.org
epss: 0.00334
epssPercentile: 0.26639
ssvc:
  exploitation: none
  automatable: 'no'
  technicalImpact: partial
  timestamp: '2026-10-21T14:24:31.859308Z'
ingestedAt: '2026-10-20T16:10:53.294Z'
---

## Overview

### Summary
The `slugTaken` endpoint returns a boolean indicating whether a slug is in use across
all document types and visibility levels, with no permission or type filter. Any logged-in
user (including editors) can enumerate the slug space of private pages, drafts, and
archived content.

### Details
`POST /api/v1/@apostrophecms/doc/slugTaken` with body `{ "slug": "target-slug" }` runs
a raw existence check against the documents collection. It does not:
- Check whether the requesting user has read permission for documents of that type.
- Filter by `visibility` (public, loginRequired, private).
- Filter by `viewRole`.
- Filter by publication status (draft vs published).

A single authenticated session can iterate the slug space to enumerate the full content
inventory of the CMS, including content the user is explicitly prohibited from viewing.

### PoC
```bash
# Any authenticated session works — editor role sufficient
curl -b "$EDITOR_JAR" -X POST \
  -H "Content-Type: application/json" \
  -d '{"slug":"known-private-page-slug"}' \
  "http://TARGET/api/v1/@apostrophecms/doc/slugTaken"
# → { "taken": true }  — confirms private page exists

curl -b "$EDITOR_JAR" -X POST \
  -H "Content-Type: application/json" \
  -d '{"slug":"zzz-nonexistent"}' \
  "http://TARGET/api/v1/@apostrophecms/doc/slugTaken"
# → { "taken": false }
```

### Impact
Information disclosure. An attacker with any authenticated session can enumerate all
slugs in the system, mapping the full content structure of the CMS including private and
admin-only content.

## Affected packages

- `apostrophe < 4.34.0`

## Remediation

Upgrade to a patched release:

- `apostrophe 4.34.0`
