GitHub Advisoryadvisory · npm

GHSA-jqw5-w6h3-44g6 ApostropheCMS import-export: NoSQL injection via update-key value lets a crafted import match and overwrite an unidentified document

MEDIUM Published 2026-10-20 Modified 2026-10-20 Official page ↗
Aliases
CVE-2026-113662
Ecosystem
npm
Packages
@apostrophecms/import-export
Severity
Moderate
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:L
Weaknesses
CWE-284, CWE-943
Reviewed
2026-10-20

Affected packages

• npm @apostrophecms/import-export: < 3.7.0 → fixed in 3.7.0

Description

Summary `@apostrophecms/import-export`'s update-by-key feature lets an imported document carry a `:key` property (for example `slug:key`) whose value is used to find an existing document to update instead of inserting a new one. `getUpdateKey()`/`insertOrUpdateDocWithKey()` (`lib/methods/import.js`) use that value directly as a MongoDB query value with no laundering: ```js const matchingDraftPromise = manager.findForEditing( req.clone({ mode: 'draft' }), { aposMode: 'draft', [updateField]: doc[updateKey] }).toObject(); ``` Archive documents are parsed with EJSON (see `lib/formats/gzip.js`), which revives objects such as `{ $ne: null }` as live values, the same untrusted data source and revival mechanism already fixed once in this module for `findSingletonAposDocId`/`findParkedAposDocId` in GHSA-79qf-vqgc-7xx3. That fix did not touch `insertOrUpdateDocWithKey`, so the identical class of bug survives here: a crafted `"slug:key": { "$ne": null }` entry in an archive's `aposDocs.json` makes the import match (and then update) an existing document the archive's author never actually identified, instead of failing to find a match. Impact Reaching this requires only an authenticated session with import access to the target type (the built-in contributor role holds this, matching the precondition of GHSA-79qf-vqgc-7xx3), and no admin interaction. Because the match uses a MongoDB operator instead of an exact value, it is not limited to a document the importer already knows the identifying field of: any existing document the importer has generic edit rights on and that satisfies the operator (which `{ $ne: null }` trivially does for any doc with a non-null value in that field) is a candidate, and Apostrophe's `findForEditing` permission filter, not the update-key logic, is the only thing narrowing which document actually gets matched and overwritten. Live-verified: a contributor-role request importing a document containing `"slug:key": { "$ne": null }` had its content applied to an existing, unrelated draft article, overwriting its title, while the importer never specified that article's real slug. Affected versions Confirmed on `main` branch HEAD as of 2026-09-04, `packages/import-export/lib/methods/import.js`. Suggested fix Launder `doc[updateKey]` to a plain string (mirroring the fix already applied to `type`/`aposLocale`/`parkedId` in GHSA-79qf-vqgc-7xx3) before using it as a query value, and fall back to the insert path when it is not a usable string.

Related

Alias · CVE (1)

  • CVE-2026-113662 ApostropheCMS is an open-source Node.js content management system. vulnerability

Weakness · CWE (2)

  • CWE-284 Improper Access Control weakness
  • CWE-943 Improper Neutralization of Special Elements in Data Query Logic weakness

References