CVE-2026-39857
Information Disclosure via `choices`/`counts` Query Parameters Bypassing publicApiProjection Field Restrictions
ApostropheCMS is an open-source Node.js content management system. Versions 4.28.0 and prior contain an authorization bypass vulnerability in the choices and counts query parameters of the REST API, where these query builders execute MongoDB distinct() operations that bypass the publicApiProjection restrictions intended to limit which fields are exposed publicly. The choices and counts parameters are processed via applyBuildersSafely before the projection is applied, and MongoDB's distinct operation does not respect projections, returning all distinct values directly. The results are returned in the API response without any filtering against publicApiProjection or removeForbiddenFields. An unauthenticated attacker can extract all distinct field values for any schema field type that has a registered query builder, including string, integer, float, select, boolean, date, slug, and relationship fields. Fields protected with viewPermission are similarly exposed, and the counts variant additionally reveals how many documents have each distinct value. Both the piece-type and page REST APIs are affected. This issue has been fixed in version 4.29.0.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- Low
- Integrity
- None
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
5.3
Information Disclosure via `choices`/`counts` Query Parameters Bypassing publicApiProjection Field Restrictions
ApostropheCMS is an open-source Node.js content management system. Versions 4.28.0 and prior contain an authorization bypass vulnerability in the choices and counts query parameters of the REST API, where these query builders execute MongoDB distinct() operations that bypass the publicApiProjection restrictions intended to limit which fields are exposed publicly. The choices and counts parameters are processed via applyBuildersSafely before the projection is applied, and MongoDB's distinct operation does not respect projections, returning all distinct values directly. The results are returned in the API response without any filtering against publicApiProjection or removeForbiddenFields. An unauthenticated attacker can extract all distinct field values for any schema field type that has a registered query builder, including string, integer, float, select, boolean, date, slug, and relationship fields. Fields protected with viewPermission are similarly exposed, and the counts variant additionally reveals how many documents have each distinct value. Both the piece-type and page REST APIs are affected. This issue has been fixed in version 4.29.0.
- Record
CVE-2026-39857- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
EUVDEUVD-2026-23108
5.3
ApostropheCMS is an open-source Node.js content management system. Versions 4.28.0 and prior contain an authorization bypass vulnerability in the choices and counts query parameters of the REST API, where these query builders execute MongoDB distinct() operations that bypass the publicApiProjection restrictions intended to limit which fields are exposed publicly. The choices and counts parameters are processed via applyBuildersSafely before the projection is applied, and MongoDB's distinct operation does not respect projections, returning all distinct values directly. The results are returned in the API response without any filtering against publicApiProjection or removeForbiddenFields. An unauthenticated attacker can extract all distinct field values for any schema field type that has a registered query builder, including string, integer, float, select, boolean, date, slug, and relationship fields. Fields protected with viewPermission are similarly exposed, and the counts variant additionally reveals how many documents have each distinct value. Both the piece-type and page REST APIs are affected. This issue has been fixed in version 4.29.0.
- Record
EUVD-2026-23108- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-c276-fj82-f2pq
5.3
ApostropheCMS: Information Disclosure via choices/counts Query Parameters Bypassing publicApiProjection Field Restrictions
Summary
The choices and counts query parameters in the Apostrophe CMS REST API allow unauthenticated users to extract distinct field values for any schema field that has a registered query builder, completely bypassing publicApiProjection restrictions that are intended to limit which fields are exposed publicly. Fields protected by viewPermission are similarly exposed.
Details
When a piece type configures publicApiProjection to enable public API access while restricting visible fields, the restriction is enforced via a MongoDB projection on the main query (piece-type/index.js:1130-1134). However, the choices and counts query builders bypass this protection through a separate code path.
The vulnerable flow:
-
getRestQueryat piece-type/index.js:1120 callsapplyBuildersSafely(req.query)(line 1122), which processes query parameters includingchoicesandcountssince both havelaundermethods (doc-type/index.js:2627-2628 and 2675-2676). -
The
publicApiProjectionis applied afterward (line 1130-1134) as a MongoDB projection on the main query. -
During query execution, the
choicesbuilder'safterhandler (doc-type/index.js:2636-2668) iterates over requested field names. The only validation is:- The field has a registered builder (
_.has(query.builders, filter)at line 2651) - The builder has a
laundermethod (line 2656)
All schema field types (string, integer, float, select, boolean, date, slug, relationship) register query builders with
laundermethods viaaddQueryBuilderinaddFieldTypes.js. - The field has a registered builder (
-
toChoices(line 2661) calls the field'schoicesfunction, which typically callssortedDistinct→toDistinct. ThetoDistinctmethod (doc-type/index.js:2811) executesdb.distinct(property, criteria)— a MongoDB operation that returns all distinct values for the given property matching the criteria. MongoDB'sdistinctoperation does not respect projections; it operates directly on the specified field regardless of any projection set on the query. -
The results are stored via
query.set('choicesResults', choices)(line 2666) and returned directly in the API response at piece-type/index.js:292-296 without any filtering againstpublicApiProjectionorremoveForbiddenFields.
The same bypass applies to viewPermission-protected fields: removeForbiddenFields (doc-type/index.js:1585-1611) only processes document results from toArray(), not the separate choices/counts data.
The page REST API has the same issue at page/index.js:371-376.
PoC
# Prerequisites:
# - An Apostrophe 4.x instance with a piece type configured with publicApiProjection
# - Example: an 'article' piece type with:
# publicApiProjection: { title: 1, slug: 1, _url: 1 }
# and additional schema fields like 'status' (select), 'priority' (integer),
# or 'internalNotes' (string) NOT in the projection
# 1. Verify normal API access only returns projected fields
curl -s 'http://localhost:3000/api/v1/article' | python3 -m json.tool
# Response results contain only: title, slug, _url (as configured)
# 2. Extract distinct values of a non-projected field via choices
curl -s 'http://localhost:3000/api/v1/article?choices=status' | python3 -m json.tool
# Response includes:
# "choices": {"status": [{"value": "draft", "label": "draft"}, {"value": "published", "label": "published"}, ...]}
# 3. Extract distinct values with document counts via counts
curl -s 'http://localhost:3000/api/v1/article?counts=priority' | python3 -m json.tool
# Response includes:
# "counts": {"priority": [{"value": 1, "label": "1", "count": 15}, {"value": 2, "label": "2", "count": 8}, ...]}
# 4. Multiple fields can be extracted at once
curl -s 'http://localhost:3000/api/v1/article?choices=status,priority,internalNotes'
Impact
- Distinct field values leaked: An unauthenticated attacker can extract all distinct values of any schema field on any piece type that has
publicApiProjection…
- Record
GHSA-c276-fj82-f2pq- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
NVD
5.3
ApostropheCMS is an open-source Node.js content management system. Versions 4.28.0 and prior contain an authorization bypass vulnerability in the choices and counts query parameters of the REST API, where these query builders execute MongoDB distinct() operations that bypass the publicApiProjection restrictions intended to limit which fields are exposed publicly. The choices and counts parameters are processed via applyBuildersSafely before the projection is applied, and MongoDB's distinct operation does not respect projections, returning all distinct values directly. The results are returned in the API response without any filtering against publicApiProjection or removeForbiddenFields. An unauthenticated attacker can extract all distinct field values for any schema field type that has a registered query builder, including string, integer, float, select, boolean, date, slug, and relationship fields. Fields protected with viewPermission are similarly exposed, and the counts variant additionally reveals how many documents have each distinct value. Both the piece-type and page REST APIs are affected. This issue has been fixed in version 4.29.0.
- Record
CVE-2026-39857- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
OSV
5.3
Information Disclosure via `choices`/`counts` Query Parameters Bypassing publicApiProjection Field Restrictions
ApostropheCMS is an open-source Node.js content management system. Versions 4.28.0 and prior contain an authorization bypass vulnerability in the choices and counts query parameters of the REST API, where these query builders execute MongoDB distinct() operations that bypass the publicApiProjection restrictions intended to limit which fields are exposed publicly. The choices and counts parameters are processed via applyBuildersSafely before the projection is applied, and MongoDB's distinct operation does not respect projections, returning all distinct values directly. The results are returned in the API response without any filtering against publicApiProjection or removeForbiddenFields. An unauthenticated attacker can extract all distinct field values for any schema field type that has a registered query builder, including string, integer, float, select, boolean, date, slug, and relationship fields. Fields protected with viewPermission are similarly exposed, and the counts variant additionally reveals how many documents have each distinct value. Both the piece-type and page REST APIs are affected. This issue has been fixed in version 4.29.0.
- Record
CVE-2026-39857- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
OSVGHSA-c276-fj82-f2pq
5.3
ApostropheCMS: Information Disclosure via choices/counts Query Parameters Bypassing publicApiProjection Field Restrictions
Summary
The choices and counts query parameters in the Apostrophe CMS REST API allow unauthenticated users to extract distinct field values for any schema field that has a registered query builder, completely bypassing publicApiProjection restrictions that are intended to limit which fields are exposed publicly. Fields protected by viewPermission are similarly exposed.
Details
When a piece type configures publicApiProjection to enable public API access while restricting visible fields, the restriction is enforced via a MongoDB projection on the main query (piece-type/index.js:1130-1134). However, the choices and counts query builders bypass this protection through a separate code path.
The vulnerable flow:
-
getRestQueryat piece-type/index.js:1120 callsapplyBuildersSafely(req.query)(line 1122), which processes query parameters includingchoicesandcountssince both havelaundermethods (doc-type/index.js:2627-2628 and 2675-2676). -
The
publicApiProjectionis applied afterward (line 1130-1134) as a MongoDB projection on the main query. -
During query execution, the
choicesbuilder'safterhandler (doc-type/index.js:2636-2668) iterates over requested field names. The only validation is:- The field has a registered builder (
_.has(query.builders, filter)at line 2651) - The builder has a
laundermethod (line 2656)
All schema field types (string, integer, float, select, boolean, date, slug, relationship) register query builders with
laundermethods viaaddQueryBuilderinaddFieldTypes.js. - The field has a registered builder (
-
toChoices(line 2661) calls the field'schoicesfunction, which typically callssortedDistinct→toDistinct. ThetoDistinctmethod (doc-type/index.js:2811) executesdb.distinct(property, criteria)— a MongoDB operation that returns all distinct values for the given property matching the criteria. MongoDB'sdistinctoperation does not respect projections; it operates directly on the specified field regardless of any projection set on the query. -
The results are stored via
query.set('choicesResults', choices)(line 2666) and returned directly in the API response at piece-type/index.js:292-296 without any filtering againstpublicApiProjectionorremoveForbiddenFields.
The same bypass applies to viewPermission-protected fields: removeForbiddenFields (doc-type/index.js:1585-1611) only processes document results from toArray(), not the separate choices/counts data.
The page REST API has the same issue at page/index.js:371-376.
PoC
# Prerequisites:
# - An Apostrophe 4.x instance with a piece type configured with publicApiProjection
# - Example: an 'article' piece type with:
# publicApiProjection: { title: 1, slug: 1, _url: 1 }
# and additional schema fields like 'status' (select), 'priority' (integer),
# or 'internalNotes' (string) NOT in the projection
# 1. Verify normal API access only returns projected fields
curl -s 'http://localhost:3000/api/v1/article' | python3 -m json.tool
# Response results contain only: title, slug, _url (as configured)
# 2. Extract distinct values of a non-projected field via choices
curl -s 'http://localhost:3000/api/v1/article?choices=status' | python3 -m json.tool
# Response includes:
# "choices": {"status": [{"value": "draft", "label": "draft"}, {"value": "published", "label": "published"}, ...]}
# 3. Extract distinct values with document counts via counts
curl -s 'http://localhost:3000/api/v1/article?counts=priority' | python3 -m json.tool
# Response includes:
# "counts": {"priority": [{"value": 1, "label": "1", "count": 15}, {"value": 2, "label": "2", "count": 8}, ...]}
# 4. Multiple fields can be extracted at once
curl -s 'http://localhost:3000/api/v1/article?choices=status,priority,internalNotes'
Impact
- Distinct field values leaked: An unauthenticated attacker can extract all distinct values of any schema field on any piece type that has
publicApiProjection…
- Record
GHSA-c276-fj82-f2pq- CVSS 3.1
- 5.3 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
apostrophenpm |
through 4.28.0 | 4.29.0 |
apostrophenpm |
before 4.29.0 | 4.29.0 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-39857 is a medium vulnerability (CVSS 5.3) in Apostrophecms Apostrophe, published April 15, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.43%, the 38th percentile. Fixed in apostrophe 4.29.0.
References
github.com/apostrophecms/apostrophe/security/advisories/GHSA-c276-fj82-f2pq
github.com/apostrophecms/apostrophe/commit/6c2b548dec2e3f7a82e8e16736603f4cd17525aa
nvd.nist.gov/vuln/detail/CVE-2026-39857
github.com/advisories/GHSA-c276-fj82-f2pq
github.com/CVEProject/cvelistV5/tree/main/cves/2026/39xxx/CVE-2026-39857.json
github.com/apostrophecms/apostrophe
Left out here: the rest of 2 source descriptions. The JSON record has them.