Alta

ApostropheCMS: Eliminación de miembros del prototipo por exclusión de proyección en @apostrophecms/db-connect causa denegación de servicio

  • Publicada: 20.10.2026
  • Actualizado: 20.10.2026 21:23

Resumen

@apostrophecms/db-connect incluye una emulación de MongoDB en memoria utilizada por sus adaptadores de SQLite, PostgreSQL y multipostgres. Su función auxiliar unsetNestedField recorre una ruta de campos con puntos controlada por el atacante sin validar los segmentos y ejecuta delete sobre la propiedad resuelta. Un usuario autenticado con pocos privilegios (cualquier rol con view-draft, que poseen todos los editores y colaboradores; reducido a cualquier usuario autenticado si guestApiAccess está habilitado) puede enviar una solicitud GET REST de tipo piece cuyo generador de consultas project contiene una clave de exclusión como constructor.prototype.hasOwnProperty. En un adaptador SQLite o PostgreSQL, esta clave llega a unsetNestedField, que resuelve Object.prototype y elimina un método en tiempo de ejecución compartido. Dado que este método se comparte en todo el proceso de Node, la eliminación interrumpe el procesamiento de solicitudes para todos los inquilinos y usuarios hasta que se reinicie el proceso, provocando una denegación de servicio persistente con una sola solicitud.

Causa raíz

El generador de consultas de proyección solo sanea los valores de proyección y nunca las claves, por lo que una clave arbitraria con puntos llega a la capa de base de datos. En los adaptadores SQLite y PostgreSQL, applyProjection aplica una proyección de exclusión en JavaScript llamando a unsetNestedField(result, field) para cada campo excluido. unsetNestedField divide el campo por . y recorre los segmentos resultantes sin protección: a diferencia de su equivalente setNestedField, ni siquiera bloquea un valor literal __proto__, y ninguna de las funciones auxiliares bloquea constructor o prototype. Dado que el objeto de trabajo es un objeto simple generado por JSON.parse(JSON.stringify(doc)), su constructor resuelve en el Object global, por lo que una ruta como constructor.prototype.<member> alcanza el Object.prototype compartido y elimina un método principal configurable.

Affected functions (repository-relative paths):
- unsetNestedField  packages/db-connect/lib/shared.js:119-129  (no segment guard; delete on resolved property)
- applyProjection   packages/db-connect/lib/shared.js:164-216  (exclusion branch calls unsetNestedField per excluded key)
Reachability driver (consumer on a SQL adapter):
- project.launder / project.finalize  packages/apostrophe/modules/@apostrophecms/doc-type/index.js:2003-2103
- getRestQuery                        packages/apostrophe/modules/@apostrophecms/piece-type/index.js:1139-1157
- SQLite adapter applyProjection call packages/db-connect/adapters/sqlite.js:906,980

Impacto

Requisitos previos: una cuenta autenticada con view-draft (cualquier rol de edición; cualquier usuario que haya iniciado sesión cuando guestApiAccess: true), y una configuración que utilice un adaptador SQLite, PostgreSQL o multipostgres. El adaptador predeterminado mongodb delega la proyección al controlador real de MongoDB y no se ve afectado. Con estas condiciones, una única solicitud GET manipulada elimina un método de prototipo compartido elegido por el atacante (por ejemplo Object.prototype.hasOwnProperty, toString o un miembro de Array.prototype). Tras la eliminación, las llamadas comunes como obj.hasOwnProperty(...) generan excepciones en todo el proceso de Node, impidiendo atender solicitudes de cualquier usuario hasta que se reinicie.

Prueba de concepto

The finding was reproduced by executing the shipped helper directly against the published db-connect source; a live consumer requires a SQLite or PostgreSQL adapter, an authenticated view-draft session, and at least one matching document.

  1. Autenticarse como cualquier usuario con view-draft en un sitio cuyo adaptador de base de datos sea sqlite, postgres o multipostgres.
  2. Emitir una lectura REST de tipo piece con una proyección de exclusión cuya clave apunte a un método de prototipo compartido.
  3. Observar que las solicitudes posteriores fallan a nivel de todo el proceso debido a la eliminación del método compartido.
GET /api/v1/@apostrophecms/article?project[constructor.prototype.hasOwnProperty]=0
Cookie: <authenticated view-draft session>
safe        benign exclusion {title:0} leaves Object.prototype.hasOwnProperty intact
VULNERABLE  exclusion projection deleted Object.prototype.hasOwnProperty (callableBefore=true, brokeEveryObject=true)
VULNERABLE  exclusion projection deleted an arbitrary Object.prototype method (__pocMarker)

Cadena de ataque

  1. Exposición: Un usuario autenticado view-draft llama al extremo GET REST GET /api/v1/@apostrophecms/<piece-type>.
  2. Control: La cadena de consulta project[constructor.prototype.hasOwnProperty]=0 es analizada por qs (con allowDots desactivado) en una clave propia con puntos literales: { 'constructor.prototype.hasOwnProperty': '0' }.
  3. Ruta: getRestQuery aplica primero los generadores de consultas; project.launder copia la clave de forma literal y fuerza solo el valor a false; project.finalize omite el valor falsy con if (!val) continue y conserva la clave; el cursor la almacena como la proyección.
  4. Protección: La anulación publicApiProjection solo se ejecuta si canAccessApi(req) es falso, por lo que se omite para emisores autenticados; no existe lista de permitidos, validación de segmentos ni protección de prototipos.
  5. Primitiva: En adaptadores SQLite o PostgreSQL, applyProjection toma la rama de exclusión y llama a unsetNestedField(result, 'constructor.prototype.hasOwnProperty'), que resuelve Object.prototype y ejecuta delete Object.prototype.hasOwnProperty.
  6. Resultado: Se elimina un método de prototipo compartido para todo el proceso de Node; las solicitudes fallan para todos los usuarios.

Evidencia de evasión

Se examinaron individualmente las protecciones pertinentes y ninguna bloquea esta ruta. El constructor launder solo sanea valores y retiene claves arbitrarias. La comprobación publicApiProjection depende de !canAccessApi(req), por lo que no se aplica a usuarios autenticados view-draft. El bucle finalize se interrumpe de forma anticipada ante valores falsy. unsetNestedField carece por completo de validación de segmentos; ni constructor ni prototype se bloquean, y constructor.prototype.<member> elude incluso la comprobación parcial __proto__. Dado que el objeto procede de JSON.parse(JSON.stringify(doc)), su constructor es el global Object, y como Object.prototype.hasOwnProperty es configurable, la eliminación se ejecuta con éxito. La corrección previa de prototype pollution solo introdujo un control {__proto__, constructor, prototype} en apos.util.set/get dentro del paquete apostrophe, sin proteger db-connect.

Versiones afectadas

  • Ecosystem: npm
  • Package: @apostrophecms/db-connect
  • Confirmed affected range: >= 1.0.0, <= 1.0.2
  • Latest release checked: 1.0.2 (npm registry)
  • Fix status: not fixed

La función no protegida unsetNestedField y la llamada applyProjection son idénticas a nivel de bytes en las versiones estables 1.0.0, 1.0.1 y 1.0.2. Las versiones preliminares (1.0.0-alpha.1, 1.0.0-alpha.2, 1.0.2-alpha.0) contienen el mismo código. La vulnerabilidad requiere un adaptador SQLite, PostgreSQL o multipostgres; el adaptador mongodb por defecto no está afectado. El paquete apostrophe declara @apostrophecms/db-connect@^1.0.1, que resuelve en el paquete afectado 1.0.2.

Corrección sugerida

Garantizar que las rutas de campo no confiables no puedan acceder a prototipos compartidos. Tanto unsetNestedField como setNestedField en packages/db-connect/lib/shared.js deben rechazar rutas que contengan __proto__, constructor o prototype, similar al control unsafePathSegments usado en apostrophe (apos.util.set/get). De forma equivalente, pueden limitarse a propiedades propias (por ejemplo mediante Object.prototype.hasOwnProperty o accesos con Map). Como mitigación temporal, se puede utilizar el adaptador predeterminado mongodb o restringir el acceso a la API REST a roles de total confianza.

Notificado por zx (GitHub: @manus-pi).

Qué hacer

Actualice apostrophe a la versión 4.33.0 o superior y @apostrophecms/db-connect a la versión 1.1.0 o superior. Como mitigación temporal, utilice el adaptador predeterminado mongodb o limite el acceso a los endpoints REST a roles de plena confianza.

Software afectado

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

PlataformaPaqueteVersiones vulnerablesCorregida en
Paquete de npm apostrophe < 4.33.0 4.33.0
Paquete de npm @apostrophecms/db-connect < 1.1.0 1.1.0

Referencias

Puntuación CVSS 7.1/10
Vector CVSS
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:H
Debilidad (CWE)
CWE-1321, CWE-400
Plataforma
npm
Paquete
apostrophe, @apostrophecms/db-connect
Publicada
20.10.2026
Actualizado
20.10.2026 21:23

Fuentes y licencias · Editado o traducido por DockRay; se mantienen los derechos y las licencias de las fuentes.

OSV / GitHub Advisory Database - GHSA-j5rq-xfvr-p969 - 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. ApostropheCMS: Eliminación de miembros del prototipo por exclusión de proyección en @apostrophecms/db-connect causa denegación de servicio esta entrada
    Alta · 7.1 CVE-2026-113666 < 4.33.0 4.33.0
  2. Alta · 7.3 CVE-2026-45011 = 4.29.0 sin corrección
  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.