¿Sabías que un simple mensaje de contacto podría darle a un atacante el control total de tu back-office? Se ha detectado una vulnerabilidad de XSS almacenado (CVE-2026-44212, CVSS 9.3) que afecta a versiones anteriores a la 8.2.6 y 9.1.1. No hagas nada sin leer esto.

📄 Ficheros afectados y parche manual paso a paso

En EasyPresta nos gusta ir al grano. Si tu tienda aún no está actualizada a las versiones seguras, puedes aplicar un parche manual hoy mismo. No te llevará más de 5 minutos.

🎯 ¿Qué fallo se ha descubierto?

Un atacante puede enviar un mensaje a través del formulario de contacto de tu tienda con un campo "email" que contiene código HTML/JS malicioso. Ese mensaje se guarda en la base de datos. Cuando tú (o tu equipo) abrís el hilo en Atención al Cliente del back-office, el código se ejecuta automáticamente. El atacante toma el control de tu panel de administración. Puede instalar módulos, modificar precios, robar datos de clientes… Vamos, un desastre.

📁 Ficheros afectados (según el parche oficial de PrestaShop)

El equipo de PrestaShop ha corregido el problema en dos ficheros:

  1. {admin_folder}/themes/default/template/controllers/customer_threads/helpers/view/view.tpl – Aquí se mostraba el email del cliente sin escaparlo.
  2. classes/Validate.php – Se ha reforzado la validación del email en origen para evitar que se guarden direcciones maliciosas.

Puedes ver los cambios exactos en el Pull Request #41342 de GitHub:
👉 https://github.com/PrestaShop/PrestaShop/pull/41342/changes

🛠️ Cómo parchear manualmente tu tienda PrestaShop 1.7 y superior

Paso 1 – Editar view.tpl

Localiza las líneas donde aparece {$thread->email}. Normalmente hay dos:

  • Una dentro de un <h3>
  • Otra dentro de un <input type="hidden">

Cambia ambas de:

{$thread->email}

a:

{$thread->email|escape:'html':'UTF-8'}

Paso 2 – Editar classes/Validate.php

La modificación necesaria en este archivo depende de la versión de PrestaShop que tengas instalada. No es lo mismo parchear un PrestaShop 1.6, 1.7, 8.0.x u 8.1.x. A continuación te mostramos las soluciones por versión. Localiza la tuya y aplica el cambio correspondiente:

PrestaShop 1.7.0 – 1.7.6.4 (Validate-1_7.php / Validate-1_7_6_5.php)

Estas dos ramas reciben un parche idéntico. La causa raíz de la vulnerabilidad es el uso de un regex con el ancla $ sin el modificador D. En PHP, $ sin /D acepta un salto de línea opcional al final de la cadena, por lo que un email como Esta dirección de correo electrónico está siendo protegida contra los robots de spam. Necesita tener JavaScript habilitado para poder verlo.\n superaba la validación. Esto permite email header injection: un atacante puede inyectar cabeceras SMTP adicionales (Bcc:, Subject:…) en cualquier correo transaccional que la tienda envíe usando ese campo.

El parche sustituye el regex por tres comprobaciones encadenadas:

// ANTES (código vulnerable)
public static function isEmail($email)
{
    return preg_match('/^[a-z0-9!#$%&\'*+\/=?^`{}|~.-]+@[a-z0-9.-]+$/i', $email);
    //                                                                   ↑ acepta \n al final
}

// DESPUÉS (Validate-1_7.php parcheado)
public static function isEmail($email)
{
    if (empty($email)) {
        return false;
    }

    // RFC 5321: máximo 254 caracteres por dirección
    if (strlen($email) > 254) {
        return false;
    }

    // Bloquea explícitamente CR, LF y TAB que permiten inyectar cabeceras
    if (preg_match('/[\r\n\t]/', $email)) {
        return false;
    }

    // Doble validación: PHP built-in + gramática RFC de SwiftMailer
    return filter_var($email, FILTER_VALIDATE_EMAIL) !== false
        && Swift_Validate::email($email);
}
  

Los dos validadores finales se aplican en serie: filter_var rechaza formatos claramente inválidos con coste mínimo, y Swift_Validate::email() aplica el análisis gramatical completo del RFC 5321 antes de que SwiftMailer use la dirección para construir la cabecera To:.

Dependencia requerida: swiftmailer/swiftmailer, que ya forma parte del núcleo de PrestaShop 1.7.

PrestaShop 1.7.6.5 – 1.7.8.x (Validate-1_7_8.php)

En la rama 1.7.8, PrestaShop ya incorpora Symfony y la librería egulias/email-validator. El parche aprovecha estos componentes para sustituir la doble validación anterior por una triple capa más expresiva, aunque sin activar aún el modo estricto de Symfony.

// DESPUÉS (Validate-1_7_8.php parcheado)
public static function isEmail($email)
{
    if (empty($email)) {
        return false;
    }

    // Capa 1: Symfony Email constraint (modo laxo)
    $validator = Validation::createValidator();
    $errors = $validator->validate($email, new Email());

    if (count($errors) > 0) {
        return false;
    }

    // Capas 2 y 3: RFC 5322 + compatibilidad con SwiftMailer
    return !empty($email) && (new EmailValidator())->isValid($email, new MultipleValidationWithAnd([
        new RFCValidation(),
        new SwiftMailerValidation(),
    ]));
}
  

Las tres capas tienen responsabilidades distintas:

  • Symfony Email constraint: primera barrera rápida con las reglas del framework.
  • RFCValidation: cumplimiento del RFC 5321/5322 mediante el parser de egulias/email-validator; detecta formatos válidos sintácticamente pero problemáticos en producción.
  • SwiftMailerValidation: garantiza que la dirección puede usarse sin riesgo de inyección dentro del motor de envío.

Dependencias requeridas: egulias/email-validator ^2.0 y symfony/validator, ambas ya en el composer.json de 1.7.8.

PrestaShop 8.0 – 8.1.x (Validate-8_1.php)

Misma estructura que 1.7.8, pero con un cambio importante: se activa el modo estricto del validador de Symfony, que aplica la gramática RFC 5322 completa en lugar del subconjunto habitual. Esto rechaza variantes como direcciones con comentarios (user(comment)@example.com) o con literales IP (user@[192.0.2.1]) que son sintácticamente válidas según el RFC pero inapropiadas en un contexto de e-commerce.

También se elimina la comprobación redundante !empty($email) en el return, ya que la guardia al inicio del método la hace innecesaria.

// DESPUÉS (Validate-8_1.php parcheado)
public static function isEmail($email)
{
    if (empty($email)) {
        return false;
    }

    $validator = Validation::createValidator();
    $errors = $validator->validate($email, new Email([
        'mode' => 'strict',   // ← nuevo respecto a 1.7.8
    ]));

    if (count($errors) > 0) {
        return false;
    }

    // Check if the value is correct according to both validators (RFC & SwiftMailer)
    return (new EmailValidator())->isValid($email, new MultipleValidationWithAnd([
        new RFCValidation(),
        new SwiftMailerValidation(),
    ]));
}
  

Dependencias requeridas: egulias/email-validator ^3.0 (la rama 8.x subió la versión mayor respecto a 1.7.8) y symfony/validator ^5.4.

PrestaShop 8.2.5 y PrestaShop 9.1.0

Si tu tienda corre 8.2.5 o PrestaShop 9.1.0, basta con que actualices a la última versión disponible de tu rama (8.2.6 y 9.1.1 respectivamente) para mantener tu tienda segura.

Paso 3 – Limpiar caché y comprobar

  • Borra la caché de PrestaShop (desde el back-office o manualmente /var/cache).
  • Prueba que en Atención al Cliente se sigue viendo el email correctamente (sin caracteres extraños).

Cómo parchear tu tienda PrestaShop 1.6.x (versiones antiguas)

Importante: Esta versión ya no recibe soporte oficial. Si aún usas PrestaShop 1.6, te recomendamos encarecidamente migrar a una versión moderna. Mientras tanto, aplica estos parches manuales.

Paso 1 – Editar message.tpl

Localiza el archivo: {admin_folder}/themes/default/template/controllers/customer_threads/message.tpl

Busca las ocurrencias de {$message.email} (normalmente unas 5 ocurrencias) y sustitúyelas por:

{$message.email|escape:'html':'UTF-8'}

Paso 2 – Editar classes/Validate.php

Modifica el método isEmail() para reforzar la validación y evitar inyección de cabeceras.

Código original (vulnerable):

public static function isEmail($email)
{
    return !empty($email) && preg_match(Tools::cleanNonUnicodeSupport('/^[a-z\p{L}0-9!#$%&\'*+\/=?^`{}|~_-]+[.a-z\p{L}0-9!#$%&\'*+\/=?^`{}|~_-]*@[a-z\p{L}0-9]+(?:[.]?[_a-z\p{L}0-9-])*\.[a-z\p{L}0-9]+$/ui'), $email);
}

Código parcheado (seguro):

public static function isEmail($email)
{
    if (empty($email) || strlen($email) > 254) {
        return false;
    }
    if (preg_match('/[\r\n\t]/', $email)) {
        return false;
    }
    return (bool)preg_match(Tools::cleanNonUnicodeSupport('/^[a-z\p{L}0-9!#$%&\'*+\/=?^`{}|~_-]+[.a-z\p{L}0-9!#$%&\'*+\/=?^`{}|~_-]*@[a-z\p{L}0-9]+(?:[.]?[_a-z\p{L}0-9-])*\.[a-z\p{L}0-9]+$/ui'), $email);
}

Paso 3 – Limpiar caché y comprobar

  • Borra la caché de PrestaShop (desde el back-office o manualmente /var/cache).
  • Prueba que en Atención al Cliente se sigue viendo el email correctamente (sin caracteres extraños).

🔁 ¿Qué pasa si no quieres tocar código?

Puedes instalar el módulo de hotfix oficial que ha publicado PrestaShop (busca "PrestaShop security patch" en sus addons). O directamente actualizar a la versión 8.2.6 (rama 8.2.x) o 9.1.1 (rama 9.1.x). Nosotros recomendamos la actualización completa cuando sea posible, pero si necesitas un parche rápido, los pasos anteriores son totalmente válidos.

✅ En resumen

Protege tu tienda YA. Si tienes prisa, aplica los dos cambios manuales que te hemos indicado. Si prefieres delegar, contacta con nosotros en EasyPresta y lo hacemos por ti.

¿Dudas? Déjanos un comentario o escríbenos directamente.


Referencias oficiales: Aviso INCIBE | GitHub Advisory