criticalCVSS 9.9Vulnerability

GHSA-hgjx-r89m-m7v4

## 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`: ```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

Properties

ghsa_id
GHSA-hgjx-r89m-m7v4
severity
critical
summary
FacturaScripts: Path traversal in UploadedFile::move() via getClientOriginalName() — arbitrary file write outside MyFiles/ leading to RCE
cvss_score
9.9
cve_id
GHSA-hgjx-r89m-m7v4
cvss_vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
is_ghsa_only
true
ghsa_published
2026-07-14T20:52:00Z
source_url
https://github.com/advisories/GHSA-hgjx-r89m-m7v4
ghsa_updated
2026-07-14T20:52:00Z

Related Entities (5)

VULNERABLE_TO (1)

[Software]composer/facturascripts/facturascripts

AFFECTS (1)

[Software]composer/facturascripts/facturascripts

HAS_WEAKNESS (2)

[Weakness]Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
[Weakness]Unrestricted Upload of File with Dangerous Type

REPORTED_BY (1)

[Source]GitHub Advisory Database

Explore deeper with Ninja Signal's threat intelligence graph