GHSA-r736-2678-fcrx: FacturaScripts vulnerable to stored XSS via product reference in sales/purchases
SummaryA stored Cross-Site Scripting (XSS) vulnerability exists in the product search modal of sales and purchases documents. An authenticated user with access to the warehouse module can create a product with a malicious reference that executes arbitrary JavaScript in the browser of any other user who opens the product search modal inside an invoice, order, or delivery note.Affected files`Core/Lib/AjaxForms/SalesModalHTML.php``Core/Lib/AjaxForms/PurchasesModalHTML.php`Vulnerability detailsThe `referencia` field of a product variant is injected directly into an HTML `onclick` attribute string without JavaScript context escaping:When a product is saved, `noHtml()` encodes `'` → `&#39;`. This appears safe in static HTML context. However, the modal HTML is later returned as a JSON response and inserted into the DOM via `innerHTML`:The browser HTML parser decodes `&#39;` → `'` during the `innerHTML` assignment, breaking out of the JavaScript string literal in the `onclick` attribute and executing the injected code.**Attack payload stored in database:** `x&#39;+alert(1)+&#39;`**Resulting `onclick` after `innerHTML` decode:**Steps to reproduce**Step 1 — Inject the payload**Log in as a user with write access to Warehouse → ProductsNavigate to `/EditProducto` and create a new product with the following values:| Field | Value |
|---|---|
| Reference | `x'+alert(1)+'` |
| Description | `test` |Save the product**Step 2 — Trigger the XSS**Make sure at least one customer exists in the system (Sales → Customers)Navigate to `/EditFacturaCliente?codcliente=<customer_code>`In the invoice form, click the product search button next to the "Referencia" fieldClick on the 'malicious' product `alert(1)`ImpactAlthough session cookies (`fsLogkey`, `fsNick`) have the `HttpOnly` flag set and cannot be read directly via `document.cookie`, the injected script runs in the victim's authenticated browser context, meaning the attacker can make arbitrary authenticated requests on their behalf, create new admin users via AJAX POST to `/EditUser`, exfiltrate any business data visible in the DOM, or redirect the user to an external site. The most critical scenario is privilege escalation: a low-privilege employee with only warehouse
access can execute JavaScript in an administrator's session without knowing their password.Recommended fixApply `htmlspecialchars()` with `ENT_QUOTES` before inserting `referencia` into the `onclick` attribute in both affected files.**`Core/Lib/AjaxForms/SalesModalHTML.php`****`Core/Lib/AjaxForms/PurchasesModalHTML.php`**Apply the same change to the equivalent line.**Why `ENT_QUOTES` is required:** `ENT_QUOTES` encodes both `"` and `'` characters. This ensures that `'` is stored as `&#39;` and — critically — remains `&#39;` after `innerHTML` assignment, because `htmlspecialchars` produces a form that the HTML parser does not decode back into a raw quote inside a JS string context.**Alternative mitigation:** replace `innerHTML` with `innerText` or a DOM-based rendering approach that never parses injected strings as HTML. This would eliminate the entire class of HTML-injection-via-innerHTML vulnerabilities in the sales and purchases
forms.CreditsOmar Ramirez
CVSS v3.1: 5.4