low

CVE-2026-113648

npm · @apostrophecms/import-export

Summary

ApostropheCMS: Missing Authentication in `cleanExport` Route

Severity
low
CVSS
3.1
EPSS
0.3% (p26)
CWE
CWE-306, CWE-862
Also known as
GHSA-rw26-wwfc-9wvm
Published
2026-10-21
Updated
2026-10-21

Advisory details

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


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

  1. Broken Access Control: Unauthenticated users can invoke cleanup operations and delete temporary export files and artifacts stored on the server.
  2. Unauthorized State Mutation: The endpoint allows modifying job records in the database via 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.

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);
       }
     }

References

Related advisories

Is your project exposed to this? Stateward checks every dependency on every pull request and flags it only if your code actually reaches it.

Check my repo

Summarize with AI

ChatGPTClaudePerplexity

Sources: CISA KEV (public domain), OSV.dev & GitHub Advisory Database (CC-BY-4.0), FIRST EPSS, NVD/CWE (public domain). Served live from the Stateward advisory database.