ApostropheCMS: Authenticated projection-exclusion prototype-member deletion in @apostrophecms/db-connect causes process-wide denial of service
## Summary `@apostrophecms/db-connect` ships an in-memory MongoDB emulation used by its SQLite, PostgreSQL, and multipostgres adapters. Its `unsetNestedField` helper walks an attacker-controlled dotted field path with no segment validation and calls `delete` on the resolved property. A low-privileged authenticated user (any role holding `view-draft`, which every editor and contributor has; reduced to any logged-in user when `guestApiAccess` is enabled) can send a piece-type REST GET request whose `project` query builder contains an exclusion key such as `constructor.prototype.hasOwnProperty`. On a SQLite or PostgreSQL adapter this key reaches `unsetNestedField`, which resolves `Object.prototype` and deletes a shared runtime method. Because that method is shared across the whole Node process, the deletion breaks request handling for every tenant and user until the process is restarted, giving a single request a persistent denial of service. ## Root Cause The projection query builder laundens only projection values, never projection keys, so an arbitrary dotted key survives to the database layer. On the SQLite and PostgreSQL adapters an exclusion projection is applied in JavaScript by `applyProjection`, which for each excluded field calls `unsetNestedField(result, field)`. `unsetNestedField` splits the field on `.` and walks the resulting segments with no guard: unlike its sibling `setNestedField`, it does not even block a literal `__proto__`, and neither helper blocks `constru
- Products
- @apostrophecms/db-connect, apostrophe
- Affected versions
- Not specified
- Fixed versions
- 1.1.0, 4.33.0
- CVEs
- CVE-2026-113666
- Confirmed fixed CVEs
- Not specified
- Updated in this feed
- 31 Oct 2026, 13:14 UTC · Revision 1
Source evidence
ApostropheCMS: Authenticated projection-exclusion prototype-member deletion in @apostrophecms/db-connect causes process-wide denial of service
core-osv · Original sourcePublished 20 Oct 2026, 18:03 UTC
## Summary `@apostrophecms/db-connect` ships an in-memory MongoDB emulation used by its SQLite, PostgreSQL, and multipostgres adapters. Its `unsetNestedField` helper walks an attacker-controlled dotted field path with no segment validation and calls `delete` on the resolved property. A low-privileged authenticated user (any role holding `view-draft`, which every editor and contributor has; reduced to any logged-in user when `guestApiAccess` is enabled) can send a piece-type REST GET request whose `project` query builder contains an exclusion key such as `constructor.prototype.hasOwnProperty`. On a SQLite or PostgreSQL adapter this key reaches `unsetNestedField`, which resolves `Object.prototype` and deletes a shared runtime method. Because that method is shared across the whole Node process, the deletion breaks request handling for every tenant and user until the process is restarted, giving a single request a persistent denial of service. ## Root Cause The projection query builder laundens only projection values, never projection keys, so an arbitrary dotted key survives to the database layer. On the SQLite and PostgreSQL adapters an exclusion projection is applied in JavaScript by `applyProjection`, which for each excluded field calls `unsetNestedField(result, field)`. `unsetNestedField` splits the field on `.` and walks the resulting segments with no guard: unlike its sibling `setNestedField`, it does not even block a literal `__proto__`, and neither helper blocks `constru
osv:GHSA-j5rq-xfvr-p969
@apostrophecms/db-connect
Fixed versions: 1.1.0
apostrophe
Fixed versions: 4.33.0
Complete source record
{
"id": "43d765f351155008b5061fd12fdf03489ee955c999a5d37aa62fefadaa789fa1",
"url": "https://osv.dev/vulnerability/GHSA-j5rq-xfvr-p969",
"method": "structured",
"payload": {
"kind": "advisory",
"title": "ApostropheCMS: Authenticated projection-exclusion prototype-member deletion in @apostrophecms/db-connect causes process-wide denial of service",
"summary": "## Summary `@apostrophecms/db-connect` ships an in-memory MongoDB emulation used by its SQLite, PostgreSQL, and multipostgres adapters. Its `unsetNestedField` helper walks an attacker-controlled dotted field path with no segment validation and calls `delete` on the resolved property. A low-privileged authenticated user (any role holding `view-draft`, which every editor and contributor has; reduced to any logged-in user when `guestApiAccess` is enabled) can send a piece-type REST GET request whose `project` query builder contains an exclusion key such as `constructor.prototype.hasOwnProperty`. On a SQLite or PostgreSQL adapter this key reaches `unsetNestedField`, which resolves `Object.prototype` and deletes a shared runtime method. Because that method is shared across the whole Node process, the deletion breaks request handling for every tenant and user until the process is restarted, giving a single request a persistent denial of service. ## Root Cause The projection query builder laundens only projection values, never projection keys, so an arbitrary dotted key survives to the database layer. On the SQLite and PostgreSQL adapters an exclusion projection is applied in JavaScript by `applyProjection`, which for each excluded field calls `unsetNestedField(result, field)`. `unsetNestedField` splits the field on `.` and walks the resulting segments with no guard: unlike its sibling `setNestedField`, it does not even block a literal `__proto__`, and neither helper blocks `constru",
"evidence": "osv:GHSA-j5rq-xfvr-p969",
"products": [
{
"name": {
"value": "@apostrophecms/db-connect",
"evidence": "/affected/0/package/name"
},
"prerequisites": [],
"fixed_versions": [
{
"value": "1.1.0",
"evidence": "/affected/0/ranges"
}
],
"affected_versions": []
},
{
"name": {
"value": "apostrophe",
"evidence": "/affected/1/package/name"
},
"prerequisites": [],
"fixed_versions": [
{
"value": "4.33.0",
"evidence": "/affected/1/ranges"
}
],
"affected_versions": []
}
],
"severity": "high",
"structured": {
"id": "GHSA-j5rq-xfvr-p969",
"aliases": [
"CVE-2026-113666",
"GHSA-j5rq-xfvr-p969"
],
"metrics": [
{
"type": "CVSS_V3",
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:H"
}
],
"affected": [
{
"ranges": [
{
"type": "SEMVER",
"events": [
{
"introduced": "0"
},
{
"fixed": "1.1.0"
}
]
}
],
"package": {
"name": "@apostrophecms/db-connect",
"purl": "pkg:npm/%40apostrophecms/db-connect",
"ecosystem": "npm"
},
"database_specific": {
"source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-j5rq-xfvr-p969/GHSA-j5rq-xfvr-p969.json"
}
},
{
"ranges": [
{
"type": "SEMVER",
"events": [
{
"introduced": "0"
},
{
"fixed": "4.33.0"
}
]
}
],
"package": {
"name": "apostrophe",
"purl": "pkg:npm/apostrophe",
"ecosystem": "npm"
},
"database_specific": {
"source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-j5rq-xfvr-p969/GHSA-j5rq-xfvr-p969.json"
}
}
],
"modified": "2026-10-20T18:15:04.524962165Z",
"provider": "osv",
"references": [
"https://github.com/apostrophecms/apostrophe/security/advisories/GHSA-j5rq-xfvr-p969",
"https://github.com/apostrophecms/apostrophe/commit/9500b8b0e1d630d5e07fbb5fd2c25ed0943845ce",
"https://github.com/apostrophecms/apostrophe/commit/f84fd41cbf6c22eb8d0008fc9c25df1f7130b350",
"https://github.com/apostrophecms/apostrophe",
"https://github.com/apostrophecms/apostrophe/releases/tag/@apostrophecms/db-connect@1.1.0",
"https://github.com/apostrophecms/apostrophe/releases/tag/apostrophe@4.33.0"
],
"provider_metadata": {
"cwe_ids": [
"CWE-1321",
"CWE-400"
],
"severity": "HIGH",
"github_reviewed": true,
"nvd_published_at": null,
"github_reviewed_at": "2026-10-20T18:03:50Z"
}
},
"related_cves": [
{
"value": "CVE-2026-113666",
"evidence": "/aliases"
}
],
"security_relevant": true,
"severity_evidence": "/database_specific/severity"
},
"source_id": "core-osv",
"document_id": 390138,
"published_at": "2026-10-20T18:03:50+00:00"
}