GitHub Advisoryadvisory · npm

GHSA-gmfx-5g6x-rr72 ApostropheCMS: Path traversal in uploadfs

LOW Published 2026-10-20 Modified 2026-10-20 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