Media

ApostropheCMS: publicApiProjection Bypass via project Query Builder in Piece-Type REST API

  • Publicada: 16.04.2026
  • Actualizado: 11.10.2026 10:22

Summary

The getRestQuery method in the @apostrophecms/piece-type module checks whether a MongoDB projection has already been set before applying the admin-configured publicApiProjection. An unauthenticated attacker can supply a project query parameter in the REST API request to pre-populate the projection state, causing the security-enforced publicApiProjection to be skipped entirely. This allows disclosure of fields that the site administrator explicitly restricted from public access.

Details

When an unauthenticated user queries the piece-type REST API, the getRestQuery method processes the request at modules/@apostrophecms/piece-type/index.js:1120:

js
// piece-type/index.js:1120-1137
getRestQuery(req, omitPermissionCheck = false) {
  const query = self.find(req).attachments(true);
  query.applyBuildersSafely(req.query);          // [1] attacker input applied first
  if (!omitPermissionCheck && !self.canAccessApi(req)) {
    if (!self.options.publicApiProjection) {
      query.and({
        _id: null
      });
    } else if (!query.state.project) {            // [2] checks if projection already set
      query.project({
        ...self.options.publicApiProjection,
        cacheInvalidatedAt: 1
      });
    }
  }
  return query;
},

At [1], applyBuildersSafely iterates over all query string parameters and invokes their corresponding builder methods. The project builder exists in @apostrophecms/doc-type with a launder method (doc-type/index.js:1876) that sanitizes values to booleans:

js
// doc-type/index.js:1875-1889
project: {
  launder (p) {
    if (!p || typeof p !== 'object' || Array.isArray(p)) {
      return {};
    }
    const projection = Object.entries(p).reduce((acc, [ key, val ]) => {
      return {
        ...acc,
        [key]: self.apos.launder.boolean(val)
      };
    }, {});
    return projection;
  },

When a request includes ?project[someField]=1, the builder sets query.state.project to {someField: true}. At [2], the conditional !query.state.project evaluates to false because the state is already populated, so the publicApiProjection is never applied.

For comparison, the @apostrophecms/page module's equivalent method (page/index.js:2953) unconditionally applies the projection:

js
// page/index.js:2953-2958
} else {
  query.project({
    ...self.options.publicApiProjection,
    cacheInvalidatedAt: 1
  });
}

PoC

Prerequisites: An ApostropheCMS 4.x instance with a piece-type (e.g., article) that has publicApiProjection configured to restrict fields. For example:

js
// modules/article/index.js
module.exports = {
  extend: '@apostrophecms/piece-type',
  options: {
    publicApiProjection: {
      title: 1,
      _url: 1
    }
  }
};

Step 1: Normal request — observe restricted fields are hidden:

bash
curl 'http://localhost:3000/api/v1/article'

Response returns only title and _url fields per the configured projection.

Step 2: Bypass projection by supplying project query parameter:

bash
curl 'http://localhost:3000/api/v1/article?project[internalNotes]=1&project[title]=1&project[slug]=1&project[createdAt]=1'

Response now includes internalNotes, slug, createdAt, and any other requested fields — bypassing the admin-configured publicApiProjection restriction.

Step 3: Request all default fields by projecting inclusion of sensitive fields:

bash
curl 'http://localhost:3000/api/v1/article?project[_id]=1&project[title]=1&project[slug]=1&project[visibility]=1&project[type]=1&project[createdAt]=1&project[updatedAt]=1'

All requested fields are returned, confirming the publicApiProjection is fully bypassed.

Impact

  • Information Disclosure: An unauthenticated attacker can read any field on documents that are already publicly queryable, bypassing administrator-configured field restrictions. This may expose internal notes, draft content, metadata, or other sensitive fields the administrator intentionally hid from the public API.
  • Scope: Affects all piece-type modules with publicApiProjection configured. The attacker cannot access documents they wouldn't otherwise be able to query (document-level permissions still apply), but they can read any field on accessible documents.
  • Exploitability: Trivial — requires only appending query parameters to a public URL. No authentication, special tools, or chaining required.

Recommended Fix

Remove the conditional check on query.state.project in piece-type/index.js, matching the page module's unconditional behavior. The admin-configured publicApiProjection should always override any user-supplied projection for unauthenticated users:

js
// modules/@apostrophecms/piece-type/index.js:1123-1134
// BEFORE (vulnerable):
if (!omitPermissionCheck && !self.canAccessApi(req)) {
  if (!self.options.publicApiProjection) {
    query.and({
      _id: null
    });
  } else if (!query.state.project) {
    query.project({
      ...self.options.publicApiProjection,
      cacheInvalidatedAt: 1
    });
  }
}

// AFTER (fixed):
if (!omitPermissionCheck && !self.canAccessApi(req)) {
  if (!self.options.publicApiProjection) {
    query.and({
      _id: null
    });
  } else {
    query.project({
      ...self.options.publicApiProjection,
      cacheInvalidatedAt: 1
    });
  }
}

Software afectado

Haz clic en una tecnología para ver todas sus vulnerabilidades.

PlataformaPaqueteVersiones vulnerablesCorregida en
Paquete de npm apostrophe < 4.29.0 4.29.0

Referencias

Puntuación CVSS 5.3/10
Vector CVSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
Debilidad (CWE)
CWE-200, CWE-863
Plataforma
npm
Paquete
apostrophe
Publicada
16.04.2026
Actualizado
11.10.2026 10:22

Fuentes y licencias

OSV / GitHub Advisory Database - GHSA-xhq9-58fw-859p - CC BY 4.0

Historial de vulnerabilidades: apostrophe

Todas las vulnerabilidades publicadas de este paquete (Paquete de npm), de la más reciente a la más antigua. Muestra si es un fallo aislado o un paquete que hay que vigilar.

Todas (27) en el archivo
Entradas en total
27
Primera → última
09.2020 10.2026
Sin corrección
4
Explotada en ataques
0

Distribución por gravedad

  • Crítica 2
  • Alta 8
  • Media 13
  • Baja 4

Divulgaciones por año

  1. 2020: 2
  2. 2021: 2
  3. 2022: 0
  4. 2023: 0
  5. 2024: 0
  6. 2025: 0
  7. 2026: 23
Gravedad:
  1. Alta · 7.3 CVE-2026-45011 = 4.29.0 sin corrección
  2. ApostropheCMS: publicApiProjection Bypass via project Query Builder in Piece-Type REST API esta entrada
    Media · 5.3 CVE-2026-33888 < 4.29.0 4.29.0
  3. Crítica · 9.8 CVE-2021-25979 >= 2.63.0, < 3.4.0 3.4.0

Identifica las vulnerabilidades de tu aplicación

Con la integración de DockRay y el inventario de software activado, DockRay compara las versiones notificadas de los componentes con las vulnerabilidades conocidas y avisa de las coincidencias confirmadas. La cobertura depende de la tecnología compatible y de los avisos disponibles.

Conectar tu aplicación
Newsletter DockRay

La seguridad de tus aplicaciones en tu correo

Vulnerabilidades importantes, recomendaciones concretas y consejos prácticos para tus aplicaciones. Elige tus tecnologías y sigue lo que importa para tu proyecto.

  • Un resumen diario de nuevas vulnerabilidades, también las críticas.
  • Avisos sobre actualizaciones importantes.
  • Consejos prácticos sobre seguridad y monitorización de aplicaciones.

Déjalo vacío para recibir avisos de todas las tecnologías.

Suscripción gratuita. Date de baja con un clic en cualquier correo.