GHSA-rw26-wwfc-9wvm
ApostropheCMS: Missing Authentication in `cleanExport` Route
At a glance
- Published
- Updated
- CVE
- CVE-2026-113648
- CVSS_V3
- CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N
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: ```javascript 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`: ```javascript 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: ```text 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: ```diff --- 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); } } ```
Affected packages
| Package | Versions |
|---|---|
| npm · @apostrophecms/import-export | introduced 0, fixed 3.7.1 |
References
- https://github.com/apostrophecms/apostrophe/security/advisories/GHSA-rw26-wwfc-9wvm WEB
- https://nvd.nist.gov/vuln/detail/CVE-2026-113648 ADVISORY
- https://github.com/apostrophecms/apostrophe/commit/06e4b377f3c360f9e89c32dccd7e505ad5ddf498 WEB
- https://github.com/apostrophecms/apostrophe/commit/40b989b1a9dd23d30029b8ce7668634265cfe5ea WEB
- https://github.com/apostrophecms/apostrophe PACKAGE
- https://github.com/apostrophecms/apostrophe/releases/tag/@apostrophecms/import-export@3.7.1 WEB
Sources
| Source | Licence |
|---|---|
| OSV.dev | CC-BY 4.0 — GitHub Advisory Database |