GitHub Advisoryadvisory · npm
GHSA-gmfx-5g6x-rr72 ApostropheCMS: Path traversal in uploadfs
LOW
Official page ↗
- Aliases
- CVE-2026-113651
- Ecosystem
- npm
- Packages
- uploadfs
- Severity
- Low
- CVSS vector
- CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:U/C:L/I:L/A:N
- Weaknesses
- CWE-22
- Reviewed
- 2026-10-20
Affected packages
• npm uploadfs: < 1.28.0 → fixed in 1.28.0
Description
Summary
The `uploadfs` library's local storage backend does not validate or sanitize user-supplied paths. The `prefixPath()` helper only strips double slashes (`//`) and the backend performs direct string concatenation (`uploadsPath + path`). An attacker can inject `../` sequences to escape the intended uploads directory, resulting in arbitrary file read, write, and delete on the host filesystem.
---
Details
Root Cause
`packages/uploadfs/uploadfs.js:652-655`
https://github.com/apostrophecms/apostrophe/blob/main/packages/uploadfs/uploadfs.js#L652-L655
```javascript
function prefixPath(path) {
// Resolve any double // that results from the prefix
return (self.prefix + path).replace(/\/\//g, '/');
}
```
`packages/uploadfs/lib/storage/local.js`
https://github.com/apostrophecms/apostrophe/blob/main/packages/uploadfs/lib/storage/local.js#L92-L95
https://github.com/apostrophecms/apostrophe/blob/main/packages/uploadfs/lib/storage/local.js#L102-L104
https://github.com/apostrophecms/apostrophe/blob/main/packages/uploadfs/lib/storage/local.js#L106-L108
```javascript
copyIn: function(localPath, path, options, callback) {
const uploadPath = uploadsPath + path; // [VULNERABLE]
return copyFile(localPath, uploadPath, callback);
},
streamOut: function(path, options) {
return fs.createReadStream(uploadsPath + path); // [VULNERABLE]
},
remove: function(path, callback) {
const uploadPath = uploadsPath + path; // [VULNERABLE]
fs.unlink(uploadPath, callback);
```
• `prefixPath()` does not normalize paths or reject `../`.
• The local backend concatenates the path directly into the filesystem call.
• Node.js resolves `/app/uploads/../../../tmp/pwned.txt` → `/tmp/pwned.txt`.
---
Proof of Concept (PoC)
Here is the poc files
https://drive.proton.me/urls/AKY4V5S0JR#Vw6XJdVCZafk
Build and run
```bash
docker load
Manual reproduction
```bash
Write outside uploads directory
curl -X POST http://localhost:3000/upload \
-F "path=../../../tmp/backdoor.txt" \
-F "file=@-;filename=backdoor.txt"
---
Impact
| Capability | Risk |
|------------|------|
| Arbitrary File Write | Write to `/etc/cron.d/`, `.ssh/authorized_keys`, or webroot files → Remote Code Execution |
| Arbitrary File Read | Exfiltrate `/etc/shadow`, application configs, database credentials |
| Arbitrary File Delete | Destroy system or application files → Denial of Service |
---
Remediation
Add path containment validation inside `uploadfs` (and every storage backend) before any filesystem operation:
```javascript
const path = require('path');
function safePath(base, target) {
const resolved = path.resolve(base, target);
if (!resolved.startsWith(path.resolve(base) + path.sep)) {
throw new Error('Path traversal blocked: target is outside the intended directory');
}
return resolved;
}
```
Related
Alias · CVE (1)
- CVE-2026-113651 ApostropheCMS is an open-source Node.js content management system, and uploadfs is its file storage library. vulnerability
Weakness · CWE (1)
- CWE-22 Improper Limitation of a Pathname to a Restricted Directory weakness
References
- https://github.com/apostrophecms/apostrophe/security/advisories/GHSA-gmfx-5g6x-rr72 web
- 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