GitHub Security Advisory: GHSA-r736-2678-fcrx
Package: facturascripts/facturascripts (COMPOSER)
Severity: MODERATE (CVSS 5.4)
CWE: CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
Vulnerable versions: <= 2025.92
Patched in: unpatched

Summary: FacturaScripts vulnerable to stored XSS via product reference in sales/purchases

Details:
## Summary

A 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 details

The `referencia` field of a product variant is injected directly into an HTML `onclick` attribute string without JavaScript context escaping:

```php
// SalesModalHTML.php ~line 102
$tbody .= '<tr onclick="return salesFormAction(\'add-product\', \''
    . $row['referencia']   // no htmlspecialchars() applied
    . '\');">';
```

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

```javascript
// SalesDocument.html.twig line 118
document.getElementById("findProductList").innerHTML = data.products;
```

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:**
```javascript
return salesFormAction('add-product', 'x'+alert(1)+'')
//                                        ^^^^^^^^^^ executes before the function call
```

## Steps to reproduce

**Step 1 — Inject the payload**

1. Log in as a user with write access to Warehouse → Products
2. Navigate to `/EditProducto` and create a new product with the following values:

| Field | Value |
|---|---|
| Reference | `x'+alert(1)+'` |
| Description | `test` |

3. Save the product

**Step 2 — Trigger the XSS**

1. Make sure at least one customer exists in the system (Sales → Customers)
2. Navigate to `/EditFacturaCliente?codcliente=<customer_code>`
3. In the invoice form, click the product search button next to the "Referencia" field
4. Click on the 'malicious' product `alert(1)`

<img width="1162" height="536" alt="image" src="https://github.com/user-attachments/assets/aaa2879e-c1fb-4af9-8501-bac03ca24ffe" />


## Impact

Although 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