CSIRTS // UNIFIED SECURITY ADVISORY FEEDSYS ● ONLINE · POWERED BY INTELFUSIONS.COM

GHSA-hgjx-r89m-m7v4: FacturaScripts: Path traversal in UploadedFile::move() via getClientOriginalName() — arbitrary file write outside MyFiles/ leading to RCE

criticalCVSS 9.9
Summary FacturaScripts\Core\UploadedFile::move($destiny, $destinyName) concatenates $destiny and $destinyName without normalizing the resulting path. Every caller in the codebase passes UploadedFile::getClientOriginalName() — the unsanitized client-supplied filename — as $destinyName, so an authenticated user submitting a filename containing ../ segments can write the uploaded content to any directory writable by the web-server user, escaping the intended MyFiles/ location. Because the shipped htaccess-sample (the documented production Apache configuration) excludes Dinamic/Assets/ and node_modules/ from the index.php rewrite, files written into those directories are served directly by Apache. Combined with .htaccess not being in BLOCKED_EXTENSIONS, the primitive escalates from arbitrary file write to remote code execution. Vulnerable Code Core/UploadedFile.php: private const BLOCKED_EXTENSIONS = ['phar', 'php', 'php3', 'php4', 'php5', 'php7', 'php8', 'pht', 'phtml', 'phps']; public function move(string $destiny, string $destinyName): bool { if (!$this->isValid()) { return false; } if (substr($destiny, -1) !== DIRECTORY_SEPARATOR) { $destiny .= DIRECTORY_SEPARATOR; } return $this->test ? rename($this->tmp_name, $destiny . $destinyName) : move_uploaded_file($this->tmp_name, $destiny . $destinyName); } public function getClientOriginalName(): string { return $this->name ?? ''; } isValid() only checks the extension blocklist, the upload error code, and is_uploaded_file() — it never inspects the filename for directory separators or .. segments. Six call sites pass the raw client filename straight into move(): - Core/Controller/ApiUploadFiles.php:58 — POST /api/3/uploadfiles - Core/Controller/ApiAttachedFiles.php:136 — POST /api/3/attachedfiles - Core/Lib/Widget/WidgetFile.php:84 — every form using a file widget - Core/Lib/Widget/WidgetLibrary.php:215 — library widget upload - Core/Lib/ExtendedController/DocFilesTrait.php:51 — document files trait - Core/Contro

Details

Source
GitHub Security Advisories (INTL · database · site)
Severity
critical — CVSS 9.9
Published
2026-07-14
Last updated
2026-07-14
Exploitation
Not in CISA KEV at last sync

Original advisory: https://github.com/advisories/GHSA-hgjx-r89m-m7v4

More from GitHub Security Advisories