All vulnerabilities
GHSA-p89j-gj6f-fh6g

facturascripts/facturascripts: PHP Object Injection via unserialize() of Request Data in WidgetSelect

facturascripts/facturascripts
CVSS
6.1Medium
ExploitationNo known exploitationNot in CISA KEV, which does not prove it is unexploitedCISA KEV
Exploit odds (EPSS)No scoreNo FIRST EPSS score in this snapshot yet
Fixed in2026.7Fixed versionGitHub
Published5 Oct 2026Updated 5 Oct 2026GitHub

What fixes it

  • 2026.7facturascripts/facturascripts, composerGitHubcomposer require "facturascripts/facturascripts:^2026.7"

A fixed version on one release line is not the upgrade target for every line. Check your exact version and any vendor backports.

Description

Summary

In WidgetSelect::processFormData(), when a select field is declared multiple="true" and is not readonly, the raw POST value is passed directly to unserialize($value) with no allowed_classes filter. For multiple selects the browser sends an array which SubRequest::get() re-serialises, so the code calls unserialize() to reverse it; a scalar string is returned verbatim, allowing an attacker to submit a serialized object instead. Unserializing the autoloadable XLSXWriter object invokes its __destruct(), which calls @unlink() on each attacker-set path in the protected $temp_files, giving arbitrary file deletion.

Details

  • Core/Lib/Widget/WidgetSelect.php:144 (sink: implode(',', unserialize($value)))
  • Core/Internal/SubRequest.php (SubRequest::get() returns the raw request value unsanitised)
  • vendor/mk-j/php_xlsxwriter/xlsxwriter.class.php (gadget: XLSXWriter::__destruct() unlinks each entry of its protected $temp_files)

Proof of concept

  1. Authenticate and open an edit form that has a select field named targetfield declared multiple="true".
  2. Submit targetfield as a single string (not an array) set to a serialized XLSXWriter object whose protected temp_files holds the absolute path(s) to delete:
   O:10:"XLSXWriter":1:{s:13:"\0*\0temp_files";a:1:{i:0;s:LEN:"<abs path>";}}
  1. Save the form. unserialize() builds the object and __destruct() deletes the target file(s).

Confirmed output:

BEFORE: -rw-r--r-- ... CANARY_victim_config.txt
PHP Fatal error: Uncaught TypeError: implode(): Argument #2 ... XLSXWriter given
                 in .../WidgetSelect.php:144
AFTER:  ls: cannot access '.../CANARY_victim_config.txt': No such file or directory
Control: submitting a normal array ['a','b'] returns "a,b" and deletes nothing.
Reproduced 2x, deterministic.

Impact

Any authenticated user whose session reaches an edit form containing a multiple="true" select can delete arbitrary files writable by the web-server user, with no admin privilege required. Deleting config.php reverts the ERP to its installer (denial of service and re-install hijack); deleting MyFiles/ or backups destroys invoices and attachments. The underlying unserialize() with no class filter is a PHP Object Injection primitive, reachable with any autoloadable gadget present on the server.

Credits

Discovered by Alisher Qarshibayev and reported through VulnCheck.

Text from GitHub Advisory Database

Affected versions 1

  • facturascripts/facturascripts, composer>= 2025.7, <= 2026.65GitHub