Introduction
A single malicious email address, submitted through a public contact form by an unauthenticated visitor, can give an attacker full administrative control over a PrestaShop store. CVE-2026-44212 is a stored Cross-Site Scripting vulnerability (CVSS 9.3) in PrestaShop's back office Customer Service view that chains a permissive email validator with missing output escaping to achieve session hijacking the moment a support employee opens the ticket.
PrestaShop is an open source e-commerce platform powering approximately 174,766 live websites, representing 0.7 percent of all websites with a known CMS and 3.0 percent of all e-commerce systems according to W3Techs and BuiltWith. Its broad adoption across small and mid-sized merchants means this vulnerability has ecosystem-scale exposure.
Technical Information
Root Cause
The vulnerability has two contributing factors that together create a clean exploitation path:
1. Permissive email validation. PrestaShop's Validate::isEmail() method in classes/Validate.php used Symfony's Email validation constraint configured in 'loose' mode. This mode accepts RFC 5321 quoted-string local parts, meaning an email address like "payload"@domain.com passes validation. Loose mode performs minimal format checking, which allowed structurally unusual strings containing embedded event handlers to pass validation and be stored in the database.
2. Missing output escaping in the Smarty template. The back office template at admin-dev/themes/default/template/controllers/customer_threads/helpers/view/view.tpl renders {$thread->email} without the |escape:'html':'UTF-8' modifier in two locations (approximately lines 96 and 117). Notably, adjacent variables like $customer->firstname and $customer->lastname already had the escape modifier applied. The email field was the only variable left unprotected, a classic template oversight.
The email value is rendered directly into HTML attribute contexts (value="..."). A double-quote character in the email breaks out of the attribute boundary, enabling HTML attribute injection.
Why strip_tags() Does Not Help
The email address passes through strip_tags() before storage, which removes angle brackets. However, the exploit payload uses only double-quote characters and plain ASCII text with no angle brackets at all. The strip_tags() call has no effect on the payload.
Attack Flow
- The attacker visits the target store's public
/contact-uspage. - They submit the contact form with a crafted email address containing an XSS payload built entirely from double quotes and event handler attributes (no angle brackets needed).
- PrestaShop's
isEmail()validator, running in'loose'mode, accepts the RFC 5321 quoted-string email address. - The
strip_tags()function processes the email but leaves it unchanged because it contains no angle brackets. - The payload is stored in the
ps_customer_threadtable in the database. - When any back office employee navigates to the Customer Service section and opens the affected thread, the Smarty template renders the raw email value inside
value="..."attribute contexts. - The double-quote in the email breaks out of the attribute, and the injected event handler (e.g.,
onfocus) executes JavaScript in the employee's browser session. - The attacker's JavaScript can exfiltrate the admin's session cookie, enabling full back office takeover.
The CVSS 3.1 vector is CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N. The only friction is user interaction: an employee must open the customer thread. Since reviewing support tickets is a routine daily workflow, this requirement provides minimal real world protection.
Proof of Concept
A public proof of concept was published by Hadrian.io on May 12, 2026.
Exploit Payload
The following email address payload survives all three gates (validation, strip_tags(), database storage):
" autofocus onfocus=alert(document.cookie) x="@xss.com
This payload uses only " and plain ASCII text. No angle brackets are present, so strip_tags() passes it through unchanged. When an admin opens the affected customer thread, the onfocus event handler fires alert(document.cookie), demonstrating session cookie theft.
Full Chain Scenario
An unauthenticated attacker submits the Contact Us form with the crafted email. The XSS payload is stored in the database and fires when any back office employee opens the Customer Service thread, enabling session hijacking and full administrative takeover via the stolen session cookie.
Nuclei Template for Detection
Hadrian also published a Nuclei template to detect vulnerable instances. The detection works by submitting an RFC 5321 quoted-string email (a benign probe value) to the contact form endpoint. Vulnerable instances (using Symfony's loose email validation mode) accept it and return a success message; patched versions (using strict mode) reject it with "Invalid email address."
The form submission uses the following body parameters:
id_contact=1&from="cve-2026-44212-probe"@xss-probe.invalid&message=security+probe&token={{token}}&submitMessage=Send&url=
Invocation:
nuclei -t cve-2026-44212.yaml -u http://TARGET -H "Host: TARGET_HOSTNAME"
Sample output:
[cve-2026-44212] [http] [critical] http://172.18.0.3/contact-us
Note: this template was not yet included in the official projectdiscovery/nuclei-templates repository as of May 14, 2026, but the Hadrian blog provides a full template description for custom deployment.
Patch Information
The PrestaShop team addressed CVE-2026-44212 with a two-pronged fix, shipped in versions 8.2.6 (commit 1312be7) and 9.1.1 (commit 74791ff). Both commits were authored by Matthieu Rolland.
1. Template Output Escaping (view.tpl)
The |escape:'html':'UTF-8' modifier was added to both occurrences of {$thread->email} in the Smarty template:
Display context (heading area):
- {l s="Your answer to" d='Admin.Orderscustomers.Feature'} {if isset($customer->firstname)}{$customer->firstname|escape:'html':'UTF-8'} {$customer->lastname|escape:'html':'UTF-8'} {else} {$thread->email}{/if} + {l s="Your answer to" d='Admin.Orderscustomers.Feature'} {if isset($customer->firstname)}{$customer->firstname|escape:'html':'UTF-8'} {$customer->lastname|escape:'html':'UTF-8'} {else} {$thread->email|escape:'html':'UTF-8'}{/if}
Hidden form input:
- <input type="hidden" name="msg_email" value="{$thread->email}" /> + <input type="hidden" name="msg_email" value="{$thread->email|escape:'html':'UTF-8'}" />
2. Stricter Email Validation (Validate.php)
The Symfony email validation mode was changed from permissive to strict:
$validator = Validation::createValidator(); $errors = $validator->validate($email, new Email([ - 'mode' => 'loose', + 'mode' => 'strict', ]));
Strict mode rejects RFC 5321 quoted-string addresses entirely, preventing the malicious email from reaching the database. This acts as defense in depth: even if the output escaping were somehow bypassed, the malicious payload would be rejected at the point of entry.
Taken together, the patch applies the classic secure coding principle of validate input, escape output.
Hotfix Module
For organizations unable to upgrade immediately, PrestaShop published the official hotfix module pshotfix_ghsaw9f3qc75qgx9, which supports PrestaShop 1.7, 8.x, and 9.x. The module can be installed via the command line interface or uploaded through the Module Manager.
Detection Methods
Web Server Log Analysis
The attack requires a POST request to the /contact-us endpoint with a from= parameter containing URL-encoded double-quote characters (%22). Legitimate customer emails submitted through contact forms virtually never contain double quotes. The Hadrian blog describes a Sigma-style rule sketch that targets webserver logs, selecting on cs-method: POST to a URI stem containing /contact-us where the query string includes both from= and URL-encoded " characters. A filter clause using a regex for standard email address patterns is applied as a negative condition, so only non-standard email submissions generate alerts. Security teams can adapt this logic to their SIEM of choice (Splunk, Elastic, Sentinel, etc.).
Database Integrity Check
Because this is a stored XSS, malicious payloads persist in the database even after the initial HTTP request has been logged and rotated. Defenders should query PrestaShop's ps_customer_thread table for email entries that begin with a double-quote character (") or contain spaces, ordered by date_add DESC. As Hadrian notes, "RFC 5321 quoted strings are vanishingly rare in legitimate e-commerce traffic." If your store has been running a vulnerable version, this retroactive database scan is critical for identifying payloads that may already be sitting dormant.
Version-Based Detection
All PrestaShop versions before 8.2.6 and versions 9.0.0 through 9.1.0 are affected. Dependency scanning tools like GitLab Dependency Scanning, Snyk, and Dependabot have already indexed this vulnerability and will flag affected prestashop/prestashop Composer packages. Checking the PrestaShop version via Composer (composer show prestashop/prestashop) or the back office admin panel is the simplest way to determine exposure.
Key Indicators of Compromise
Based on the Hadrian blog's analysis, defenders should watch for:
- POST requests to
/contact-uscontaining%22(URL-encoded double quote) in thefromparameter - Email values in
ps_customer_threaddatabase rows that start with"or contain spaces - HTML event handler keywords (
onfocus,autofocus,onmouseover, etc.) embedded within email address fields in customer threads - Anomalous admin session activity following the opening of a customer service thread (potential indicator of session hijacking after XSS execution)
No official IDS/IPS signatures (e.g., Snort or Suricata rules) or YARA rules have been published for this CVE at this time.
Affected Systems and Versions
| Branch | Affected Range | Fixed Version | Hotfix Module Support |
|---|---|---|---|
| 1.7.x | Multiple 1.7 releases | No core fix noted | Yes |
| 8.x | All versions prior to 8.2.6 | 8.2.6 | Yes |
| 9.x | Versions 9.0.0 through 9.1.0 | 9.1.1 | Yes |
The vulnerability affects any PrestaShop deployment where the back office Customer Service view is accessible to employees and the public Contact Us form is enabled (which is the default configuration).
Vendor Security History
PrestaShop's response to this vulnerability demonstrated strong coordination: simultaneous security releases for both the 8.x and 9.x branches, plus a dedicated hotfix module covering legacy 1.7.x installations. The multi-track approach, covering three major version families with both core patches and a standalone module, indicates mature incident response processes. The vulnerability was responsibly disclosed by Savio from Doyensec in collaboration with Anthropic Research.
References
- NVD: CVE-2026-44212
- CVE Record: CVE-2026-44212
- GitHub Advisory: GHSA-w9f3-qc75-qgx9
- GitHub Advisory (global)
- Hadrian.io: Stored XSS in PrestaShop Back Office via RFC 5321 Quoted String Email
- Fix Commit 1312be7 (8.2.6)
- Fix Commit 74791ff (9.1.1)
- PrestaShop 8.2.6 Release
- PrestaShop 8.2.6 Security Release Announcement
- PrestaShop 9.1.1 Security Release Announcement
- Hotfix Module: pshotfix_ghsaw9f3qc75qgx9
- GitLab Advisory
- OSV: GHSA-w9f3-qc75-qgx9
- Strobes: CVE-2026-44212
- W3Techs: PrestaShop Usage Statistics
- BuiltWith: PrestaShop Usage Statistics



