
CVE-2026-9811 es una vulnerabilidad de Cross-Site Scripting Almacenado (Stored XSS) que afecta a Mautic 7 (versiones 7.0.0 a 7.1.1).
CVE-2026-9811 es una vulnerabilidad de Cross-Site Scripting Almacenado (Stored XSS) que afecta a Mautic 7 (versiones 7.0.0 a 7.1.1). La vulnerabilidad existe en el componente Project Selector, donde los nombres de proyecto devueltos a través de una solicitud AJAX se insertan en la página sin una codificación de salida ni un saneamiento adecuados. Un usuario autenticado con permiso para crear proyectos puede almacenar una carga útil (payload) de JavaScript malicioso en un nombre de proyecto. Cuando otro administrador abre posteriormente un editor de entidades que contiene el selector de proyectos, el script malicioso se ejecuta en su navegador.
Propiedad Valor Producto Mautic Versiones Afectadas 7.0.0 – 7.1.1 Versión Corregida 7.1.2 Componente Project Selector Tipo de Vulnerabilidad Stored Cross-Site Scripting (XSS)
La aplicación almacena los nombres de proyecto proporcionados por usuarios autenticados y posteriormente los recupera a través de un endpoint AJAX. Al renderizar el selector de proyectos, la aplicación inserta estos valores directamente en el DOM como elementos de opción HTML, sin escapar ni sanear el contenido.
Conceptualmente:
User creates project
│
▼
Project name stored in database
│
▼
AJAX returns project name
│
▼
Inserted into DOM without sanitization
│
▼
Browser executes embedded JavaScript
Debido a que la aplicación confía en los datos almacenados, el JavaScript malicioso se ejecuta cada vez que otro usuario privilegiado carga la página vulnerable.
Attacker
│
▼
Creates a project with a malicious JavaScript payload as its name
│
▼
Payload is stored in the database
│
▼
Administrator opens an entity editor
│
▼
AJAX request retrieves project names
│
▼
Application inserts project name into the DOM without encoding
│
▼
Browser executes the malicious script
│
▼
Attacker gains actions within the administrator's session
Un atacante con permiso para crear proyectos crea un proyecto cuyo nombre contiene una carga útil de JavaScript malicioso.
Más tarde, un administrador edita otra entidad que incluye el Project Selector. El selector carga los nombres de proyecto mediante AJAX y los inserta directamente en la página. Debido a que el nombre del proyecto no está saneado, el navegador ejecuta el script incrustado con los privilegios del administrador.
Imagine que Mautic tiene un formulario como este:
POST /projects/create HTTP/1.1
Content-Type: application/x-www-form-urlencoded
projectName=Marketing Campaign
description=Email Campaign
El proyecto se guarda como:
Marketing Campaign
Paso 2: El Atacante Crea un Proyecto
En lugar de un nombre normal, el atacante introduce HTML que contiene un evento JavaScript inofensivo:
POST /projects/create HTTP/1.1
Content-Type: application/x-www-form-urlencoded
projectName=<img src="https://raw.githubusercontent.com/aj2108/cve-2026-9811/main/x" onerror="console.log('XSS Demo')">
description=Test
La base de datos almacena ahora exactamente esa cadena.
Paso 3: AJAX Devuelve el Valor Almacenado
Más tarde, un administrador abre una página que carga proyectos.
Respuesta AJAX:
{
"id": 7,
"projectName": ""
}
Paso 4: JavaScript Vulnerable
Suponga que la aplicación hace esto:
const project = response.projectName;
document.getElementById("projects").innerHTML +=
`<option>${project}</option>`;
El navegador ve:
<option>
<img src="https://raw.githubusercontent.com/aj2108/cve-2026-9811/main/x" onerror="console.log('XSS Demo')">
</option>
Dado que la aplicación insertó la cadena como HTML en lugar de texto, el navegador la interpreta como un elemento real. La imagen no se carga (src="x"), lo que provoca la ejecución del controlador onerror.
Una explotación exitosa puede permitir a un atacante:
| Métrica | Puntuación |
|---|---|
| CVSS v3.1 (CNA) | 5.4 (Media) |
NVD aún no ha publicado su propia evaluación CVSS para este CVE.
Nota: El proveedor no ha publicado el código fuente vulnerable exacto. El siguiente ejemplo ilustra únicamente el patrón de la vulnerabilidad.
// Data returned from AJAX
const project = response.projectName;
// Unsafe: inserted directly into the DOM
document.getElementById("projectSelector").innerHTML +=
`<option>${project}</option>`;
El nombre del proyecto se origina a partir de la entrada del usuario, pero se inserta en la página sin codificación HTML. Si el valor almacenado contiene HTML o JavaScript, el navegador lo interpreta como contenido ejecutable en lugar de texto plano.
const option = document.createElement("option");
// Safe: assign as text, not HTML
option.textContent = response.projectName;
document.getElementById("projectSelector").appendChild(option);
O bien, si la salida HTML es inevitable, asegúrese de codificar correctamente la salida antes de la inserción.
El uso de textContent (o una API segura equivalente) garantiza que cualquier carácter especial se trate como texto plano en lugar de HTML o JavaScript ejecutable. Incluso si un nombre de proyecto malicioso se almacena en la base de datos, se mostrará literalmente en lugar de ejecutarse.