Live › vulnerability › CVE-2026-113648
Go to dashboardThe ApostropheCMS import-export module exposes POST /api/v1/@apostrophecms/import-export/clean-export without an authentication check, so anonymous visitors holding the site's CSRF cookie can trigger cleanup. An attacker can delete temporary export files on the server and mark arbitrary import/export job records as completed or dismiss notifications.
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.1 | 3.7.1 |
3.7.1 in package-lock.json or the installed node_modules3.7.1 or laterEach row is the first time that source carried this signal. The analyst’s rows are its own findings.
The API endpoint POST /api/v1/@apostrophecms/import-export/clean-export in @apostrophecms/import-export lacks authentication and authorization checks. Any client—including unauthenticated anonymous users who have obtained the standard CSRF cookie from visiting the site—can directly invoke this route and trigger the underlying self.cleanExport(req) method.
POST /api/v1/@apostrophecms/import-export/clean-exportpackages/import-export/lib/apiRoutes.js (lines 32–34)packages/import-export/lib/methods/import.js (lines 1271–1324)In packages/import-export/lib/apiRoutes.js, the get.related handler explicitly validates that the caller is logged in:
get: {
async related(req) {
if (!req.user) {
throw self.apos.error('forbidden');
}
// ...
}
}
In contrast, post.cleanExport (as well as post.overrideDuplicates) lacks any verification of req.user:
post: {
async overrideDuplicates(req) {
return self.overrideDuplicates(req);
},
async cleanExport(req) {
return self.cleanExport(req); // <-- No authentication check
}
}
Because ApostropheCMS does not enforce authentication globally on all apiRoutes, omitting an explicit if (!req.user) guard allows anonymous requests to pass directly through to the business logic layer.
When sending an unauthenticated POST request with the site’s CSRF cookie (issued to any visitor on GET /), the request bypasses access control entirely and executes self.cleanExport(req), as demonstrated by the server stack trace:
at Object.cleanExport (.../packages/import-export/lib/methods/import.js)
at .../packages/apostrophe/modules/@apostrophecms/module/index.js:193:30
This confirms that execution directly reaches the core import-export handler without an authenticated session.
req.body.jobId (forcing them to ended: true, status: 'completed') and dismissing notifications via req.body.notificationId without verifying whether the resources belong to the requesting caller.Enforce an authentication check in packages/import-export/lib/apiRoutes.js before executing the underlying methods:
--- a/packages/import-export/lib/apiRoutes.js
+++ b/packages/import-export/lib/apiRoutes.js
@@ -26,10 +26,16 @@ module.exports = self => {
get: { ... },
post: {
async overrideDuplicates(req) {
+ if (!req.user) {
+ throw self.apos.error('forbidden');
+ }
return self.overrideDuplicates(req);
},
async cleanExport(req) {
+ if (!req.user) {
+ throw self.apos.error('forbidden');
+ }
return self.cleanExport(req);
}
}
This page as .md · .json · in your agent: get_signal("CVE-2026-113648")
GitHub Advisory Database, CC-BY 4.0 · NVD data is provided by NIST and is public domain. Posts quoted belong to their authors.