ApostropheCMS: Missing Authentication in `cleanExport` Route
#### 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 reque
- Products
- @apostrophecms/import-export
- Affected versions
- Not specified
- Fixed versions
- 3.7.1
- CVEs
- CVE-2026-113648
- Confirmed fixed CVEs
- Not specified
- Updated in this feed
- 31 Oct 2026, 15:36 UTC · Revision 1
Source evidence
ApostropheCMS: Missing Authentication in `cleanExport` Route
core-osv · Original sourcePublished 21 Oct 2026, 17:13 UTC
#### 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 reque
osv:GHSA-rw26-wwfc-9wvm
@apostrophecms/import-export
Fixed versions: 3.7.1
Complete source record
{
"id": "f89dc4a4a6b5f1c63a2fb7279e0352b6e4bc0605b3a20fbfe6d130e933e65efd",
"url": "https://osv.dev/vulnerability/GHSA-rw26-wwfc-9wvm",
"method": "structured",
"payload": {
"kind": "advisory",
"title": "ApostropheCMS: Missing Authentication in `cleanExport` Route",
"summary": "#### 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 reque",
"evidence": "osv:GHSA-rw26-wwfc-9wvm",
"products": [
{
"name": {
"value": "@apostrophecms/import-export",
"evidence": "/affected/0/package/name"
},
"prerequisites": [],
"fixed_versions": [
{
"value": "3.7.1",
"evidence": "/affected/0/ranges"
}
],
"affected_versions": []
}
],
"severity": "low",
"structured": {
"id": "GHSA-rw26-wwfc-9wvm",
"aliases": [
"CVE-2026-113648",
"GHSA-rw26-wwfc-9wvm"
],
"metrics": [
{
"type": "CVSS_V3",
"score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N"
}
],
"affected": [
{
"ranges": [
{
"type": "SEMVER",
"events": [
{
"introduced": "0"
},
{
"fixed": "3.7.1"
}
]
}
],
"package": {
"name": "@apostrophecms/import-export",
"purl": "pkg:npm/%40apostrophecms/import-export",
"ecosystem": "npm"
},
"database_specific": {
"source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-rw26-wwfc-9wvm/GHSA-rw26-wwfc-9wvm.json"
}
}
],
"modified": "2026-10-21T17:28:21.930781411Z",
"provider": "osv",
"references": [
"https://github.com/apostrophecms/apostrophe/security/advisories/GHSA-rw26-wwfc-9wvm",
"https://nvd.nist.gov/vuln/detail/CVE-2026-113648",
"https://github.com/apostrophecms/apostrophe/commit/06e4b377f3c360f9e89c32dccd7e505ad5ddf498",
"https://github.com/apostrophecms/apostrophe/commit/40b989b1a9dd23d30029b8ce7668634265cfe5ea",
"https://github.com/apostrophecms/apostrophe",
"https://github.com/apostrophecms/apostrophe/releases/tag/@apostrophecms/import-export@3.7.1"
],
"provider_metadata": {
"cwe_ids": [
"CWE-306",
"CWE-862"
],
"severity": "LOW",
"github_reviewed": true,
"nvd_published_at": "2026-10-20T17:17:35Z",
"github_reviewed_at": "2026-10-21T17:13:28Z"
}
},
"related_cves": [
{
"value": "CVE-2026-113648",
"evidence": "/aliases"
}
],
"security_relevant": true,
"severity_evidence": "/database_specific/severity"
},
"source_id": "core-osv",
"document_id": 397802,
"published_at": "2026-10-21T17:13:28+00:00"
}