GitHub Advisoryadvisory · npm

GHSA-86wm-68pq-5jwq ApostropheCMS: Unauthenticated resource exhaustion via pre-auth aposBigUpload processing in @apostrophecms/import-export

HIGH Published 2026-10-21 Modified 2026-10-21 Official page ↗
Aliases
CVE-2026-113711
Ecosystem
npm
Packages
apostrophe, @apostrophecms/import-export
Severity
High
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weaknesses
CWE-400, CWE-770
Reviewed
2026-10-21

Affected packages

• npm apostrophe: < 4.33.0 → fixed in 4.33.0 • npm @apostrophecms/import-export: < 3.7.0 → fixed in 3.7.0

Description

Summary A potential unauthenticated denial-of-service vulnerability exists in the chunked import upload path used by `@apostrophecms/import-export`. The affected import API routes invoke: `self.apos.http.bigUploadMiddleware()` before the actual import handler performs its authentication check. Because no `authorize` callback is supplied to `bigUploadMiddleware()`, unauthenticated requests can reach the `aposBigUpload` `start`, `chunk`, and `end` operations before the later `req.user` check rejects the import. As a result, an unauthenticated remote attacker can create server-side upload state, write chunk data to upload storage, trigger temporary-file processing, and cause attacker-controlled cleanup operations before authentication is enforced. Affected Component Package: `@apostrophecms/import-export` Confirmed affected version: `3.6.2` Potential earlier affected versions: The issue may affect earlier 3.x releases in which the current big-upload-based import implementation is present. I have not yet fully verified the exact introduction version and recommend that the maintainers confirm the affected version range. Vulnerability Type Primary: CWE-400 — Uncontrolled Resource Consumption Related: CWE-306 — Missing Authentication for Critical Function CWE-770 — Allocation of Resources Without Limits or Throttling Technical Details The page import route registers the following middleware chain: `packages/import-export/modules/@apostrophecms/import-export-page/index.js` ```javascript importExportImport: [ self.apos.http.bigUploadMiddleware(), async (req) => { return self.apos.modules['@apostrophecms/import-export'] .import(req, self.__meta.name); } ] ``` No `authorize` callback is passed to `bigUploadMiddleware()`. The `bigUploadMiddleware()` implementation explicitly supports an `authorize` callback and performs that authorization before processing the `aposBigUpload` protocol when supplied. Without that callback, requests containing: `aposBigUpload[type]=start` `aposBigUpload[type]=chunk` or `aposBigUpload[type]=end` are processed immediately. The actual authentication check occurs later in: `packages/import-export/lib/methods/import.js` ```javascript async import(req, moduleName) { if (!req.user) { throw self.apos.error('forbidden'); } ``` This means authentication occurs only after the chunked-upload middleware has already performed server-side work. Attack Flow 1. Start An unauthenticated attacker submits an `aposBigUpload[type]=start` request. The server generates an upload ID and stores attacker-supplied upload metadata, including the declared `chunks` count. 2. Chunk The attacker can upload chunk data. `bigUploadChunk()` copies attacker-controlled data into: `/big-uploads/--` 3. End The attacker sends an `aposBigUpload[type]=end` request. `bigUploadEnd()` begins processing the upload and creates temporary files before invoking the downstream import handler. Only after this processing completes does execution reach the later authentication check in `import()`. 4. Cleanup amplification The attacker-controlled `chunks` value is also used by `bigUploadCleanupOne()`: ```javascript for (const { chunks } of Object.values(bigUpload.files)) { for (let i = 0; (i /tmp/chunk.bin curl -s -X POST \ 'http://localhost:3000/api/v1/@apostrophecms/page/importExportImport?aposBigUpload[type]=chunk&aposBigUpload[id]=&aposBigUpload[n]=0&aposBigUpload[chunk]=0' \ -F 'chunk=@/tmp/chunk.bin;type=application/octet-stream' ``` The request succeeds and causes server-side upload storage to be used. Finalize the upload ```bash curl -i -X POST \ 'http://localhost:3000/api/v1/@apostrophecms/page/importExportImport?aposBigUpload[type]=end&aposBigUpload[id]=' ``` Observed behavior: • `start` returns HTTP 200 and an upload ID without authentication. • `chunk` returns HTTP 200 and results in server-side chunk storage. • `end` eventually reaches the downstream authentication check and is rejected. • However, the server-side big-upload processing has already occurred before that authentication rejection. In my isolated harness: • `chunks=1` resulted in one cleanup removal attempt. • `chunks=50` resulted in 50 cleanup removal attempts. This demonstrates that the attacker-controlled chunk count directly influences server-side cleanup work. Security Impact The vulnerability allows an unauthenticated remote attacker to cause server-side storage and filesystem operations that should only be reachable by authorized import users. Possible consequences include: • Consumption of upload and temporary storage. • Creation of server-side upload state by unauthenticated users. • Repeated filesystem I/O. • Cleanup amplification based on attacker-controlled chunk counts. • Potential service degradation or denial of service when the attack is repeated or sufficiently amplified. Root Cause Authentication is enforced in the downstream import handler rather than before the chunked-upload middleware. The middleware itself already supports an `authorize` callback specifically for preventing unauthorized use of the big-upload functionality. Suggested Remediation Require authentication before any `aposBigUpload` operation is processed. For example: • Pass an appropriate `authorize` callback to `bigUploadMiddleware()` on all import routes. • Reject unauthenticated users before `start`, `chunk`, or `end`. • Enforce reasonable limits on declared chunk counts. • Validate declared size against actual uploaded data. • Introduce per-user and global storage/rate limits. • Ensure temporary files are removed when downstream processing fails. • Add regression tests confirming that anonymous `start`, `chunk`, and `end` requests are rejected before upload state or files are created. Relevant reviewed commit: `d3ff8c9bb001be1acf7fdc3f035190250ac64b45` Researcher Credit Kai Zhi GitHub: https://github.com/kaizhi888

Related

Alias · CVE (1)

  • CVE-2026-113711 ApostropheCMS is an open-source Node.js content management system. vulnerability

Weakness · CWE (2)

  • CWE-400 Uncontrolled Resource Consumption weakness
  • CWE-770 Allocation of Resources Without Limits or Throttling weakness

References