@apostrophecms/import-export: ApostropheCMS: Missing Authentication in `cleanExport` Route
What fixes it
- 3.7.1@apostrophecms/import-export, npmGitHub
npm install @apostrophecms/import-export@3.7.1
A fixed version on one release line is not the upgrade target for every line. Check your exact version and any vendor backports.
Description
1. Summary
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.
---
2. Affected Files & Endpoints
- Endpoint:
POST /api/v1/@apostrophecms/import-export/clean-export - Route Definition:
packages/import-export/lib/apiRoutes.js(lines 32–34) - Method Implementation:
packages/import-export/lib/methods/import.js(lines 1271–1324)
---
3. Root Cause Analysis
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.
---
4. Evidence
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.
---
5. Impact
- Broken Access Control: Unauthenticated users can invoke cleanup operations and delete temporary export files and artifacts stored on the server.
- Unauthorized State Mutation: The endpoint allows modifying job records in the database via
req.body.jobId(forcing them toended: true, status: 'completed') and dismissing notifications viareq.body.notificationIdwithout verifying whether the resources belong to the requesting caller.
---
6. Suggested Remediation (Patch)
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);
}
}Text from GitHub Advisory Database
Affected versions 4
- @apostrophecms/import-export, npm< 3.7.1GitHub
- apostropheaffected: < 4.34.0CVE List
- import-exportaffected: < 3.7.1CVE List
- @apostrophecms/import-export, npmfrom first release, fixed in 3.7.1OSV
References 6
- github.com/apostrophecms/apostrophe/commit/06e4b377f3c360f9e89c32dccd7e505ad5ddf498Fixvia CVE List
- github.com/apostrophecms/apostrophe/commit/40b989b1a9dd23d30029b8ce7668634265cfe5eaFixvia CVE List
- github.com/apostrophecms/apostrophe/releases/tag/@apostrophecms/import-export@3.7.1Fixvia CVE List
- github.com/apostrophecms/apostrophe/security/advisories/GHSA-rw26-wwfc-9wvmAdvisoryvia CVE List
- github.com/advisories/GHSA-rw26-wwfc-9wvmAdvisoryvia GitHub
- nvd.nist.gov/vuln/detail/CVE-2026-113648Referencevia GitHub