
Loading

Loading
We use strictly necessary cookies to run this site, and analytics cookies to understand how it's used. See our Privacy Policy for details.
A GitHub-reviewed security advisory, not necessarily under active exploitation the way our CISA KEV advisories are, but a real, disclosed vulnerability in an open-source dependency.
Affected packages
Vulnerable: < 3.7.0
Patched in 3.7.0
Details
@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.
Talk to us about this
Find out whether this dependency (or others like it) is actually reachable in your codebase.
Get help patching, or building dependency-scanning into your pipeline going forward.
A secure code review or supply chain review finds this before an advisory does.