Security Digest · Critical advisory (no CVE assigned)
GHSA-hgjx-r89m-m7v4: FacturaScripts: Path traversal in UploadedFile::move() via getClientOriginalName() — arbitrary file write outside MyFiles/ leading to RCE
Summary FacturaScripts\Core\UploadedFile::move($destiny, $destinyName) concatenates $destiny and $destinyName without normalizing the resulting path.
CVSS 9.9 Critical GitHub-reviewed · critical
Should you act?
- Only if you depend on one of the packages below, directly or transitively, in a vulnerable version. Check your lockfile with
composer audit. - No CVE has been assigned, so it will not appear in CVE-based scanners that ignore GitHub advisories.
npm audit,pip-auditand Dependabot do read GitHub advisories.
Affected packages
| Ecosystem | Package | Vulnerable | First fixed |
|---|---|---|---|
| Composer (PHP) | facturascripts/facturascripts | >= 2025, <= 2026.2 | none listed |
Details
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 nodemodules/ from the index.php rewrite, files written into those directories are served directly by Apache. Combined with .htaccess not being in BLOCKEDEXTENSIONS, the primitive escalates from arbitrary file write to remote code execution.
Vulnerable Code
Core/UploadedFile.php:
isValid() only checks the extension blocklist, the upload error code, and isuploadedfile() — 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/Controller/AdminPlugins.php:260 — plugin (zip) upload
CVSS: 9.9 (v3.1) CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
Sources and references
- GitHub Advisory GHSA-hgjx-r89m-m7v4 github.com
- github.com github.com
Critical Composer (PHP) advisories · Today’s Security Digest