Live › vulnerability › CVE-2026-113662
Go to dashboardThe @apostrophecms/import-export package lets an archive's update-key field be used as a raw MongoDB query value, so a crafted operator object like { $ne: null } can match and overwrite an existing document the archive author did not identify. An attacker with a contributor-level import session can overwrite content in existing documents they have edit rights on.
Summary written from the sources below. Check the originals before acting.
First seen by InfraStack 2026-10-23 19:11 UTC, 3h before NVD. All times on this page are UTC.
| Product | Ecosystem | Affected | Fixed in |
|---|---|---|---|
| @apostrophecms/import-export | npm | < 3.7.0 | 3.7.0 |
Check the installed version: npm ls @apostrophecms/import-export Affected if the version is below 3.7.0.
Upgrade @apostrophecms/import-export to 3.7.0 or later.
Each row is the first time that source carried this signal. The analyst’s rows are its own findings.
@apostrophecms/import-export's update-by-key feature lets an imported
document carry a <field>: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:
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.
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.
Confirmed on main branch HEAD as of 2026-09-04,
packages/import-export/lib/methods/import.js.
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.
This page as .md · .json · in your agent: get_signal("CVE-2026-113662")
GitHub Advisory Database, CC-BY 4.0 · NVD data is provided by NIST and is public domain. Posts quoted belong to their authors.