How CVE-2026-96568 Works
Both checkout paths — the admin-ajax.php action mprm_process_checkout and the front-end mprm_purchase form — accept submissions from logged-out visitors, and the 2.4.14 handler checks neither a nonce nor a capability. The submitted phone_number value passes through sanitize_text_field, which strips tags but leaves quote characters and entity-encoded text intact. The value is saved to the order's _mprm_order_phone_number meta and the customer record's telephone field. When an administrator opens the Orders or Customers list table, Order::column_order_title() and the customers report drop that stored value straight into HTML — an href attribute and cell text with no escaping. The stored script then runs in the admin's browser under the admin's session, a scope change consistent with the CVSS:3.1 vector behind its 7.2 score.
BitFire FREE's WAF Stops the Injection at Delivery
The exploit lives or dies at delivery: the malicious content must arrive inside the phone_number field of a checkout POST. BitFire FREE's Web Application Firewall inspects exactly that — form data and POST bodies — before WordPress runs any plugin code. Its cross-site scripting detection matches the injected script payload in the request and blocks it on the spot, so nothing hostile is stored and the admin Orders and Customers tables have nothing dangerous to render. Because this is behavior-based request inspection rather than a CVE-specific virtual patch, it also covers variants of the same attack. Both delivery routes, the admin-ajax.php action and the front-end form, cross this filter. BitFire WAF ships in BitFire FREE for eligible non-commercial sites; commercial sites require the appropriate commercial license.
The 2.4.15 Fix: Validate Input, Escape Output
Version 2.4.15 attacks the flaw at both ends. On input, purchase_form_validate_phone() now type-checks the submitted value and rejects it with a checkout error when preg_match('/[^0-9 +().-]/', $number) matches — only digits and phone punctuation survive, so quotes and markup can no longer be stored. On output, column_order_title() wraps the admin URL in esc_url(), names in esc_html(), and the phone number in both esc_attr() and esc_html(); the customers table gains the same escaping on its telephone, email, and name columns. The output fix also neutralizes any hostile values stored by earlier versions. Update to 2.4.15 or later immediately — but patching a plugin does not evict an attacker who already used it.
If Your Site Was Affected, Investigate for Persistence
Stored XSS gives an attacker a foothold in an administrator's browser, and a compromised admin session is how WordPress sites get rearmed. If your restaurant site ever ran 2.4.14 or earlier, treat it as possibly compromised: patch first, then run BitFire Threat Hunter. Threat Hunter performs a thorough post-compromise investigation and digs up exactly the artifacts that matter here — backdoor WordPress administrator accounts, hidden database triggers, suspicious database content such as planted payloads, long-running PHP processes, and droppers that can restore malware or reinfect the site. Remove every finding, rotate administrator, application-password, and other relevant credentials, and do not assume a missing malicious file means the site is clean.
Conclusion: Block the Request, Close the Door
Stored XSS in a checkout field is one of the easiest WordPress attacks to deliver and one of the most damaging to absorb, because it detonates in your admin session. BitFire gives you two decisive moves: the FREE WAF that blocks the poisoned checkout request before WordPress processes it, and BitFire Threat Hunter to hunt down any persistence a prior compromise left behind. Patch to 2.4.15 today, deploy BitFire, and run Threat Hunter once — before an attacker decides your order list is the easiest door into your site.