GitHub Advisoryadvisory · npm
GHSA-86wm-68pq-5jwq ApostropheCMS: Unauthenticated resource exhaustion via pre-auth aposBigUpload processing in @apostrophecms/import-export
HIGH
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
References
- https://github.com/apostrophecms/apostrophe/security/advisories/GHSA-86wm-68pq-5jwq web
- https://nvd.nist.gov/vuln/detail/CVE-2026-113711 advisory
- https://github.com/apostrophecms/apostrophe/commit/9500b8b0e1d630d5e07fbb5fd2c25ed0943845ce web
- https://github.com/apostrophecms/apostrophe/commit/f84fd41cbf6c22eb8d0008fc9c25df1f7130b350 web
- https://github.com/apostrophecms/apostrophe package
- https://github.com/apostrophecms/apostrophe/releases/tag/[email protected] web