
CVE-2026-9811 is a Stored Cross-Site Scripting (Stored XSS) vulnerability affecting Mautic 7 (versions 7.0.0 through 7.1.1).
CVE-2026-9811 é uma vulnerabilidade de Cross-Site Scripting Armazenado (Stored XSS) que afeta o Mautic 7 (versões 7.0.0 a 7.1.1).A vulnerabilidade existe no componente Project Selector, onde os nomes de projetos retornados por meio de uma solicitação AJAX são inseridos na página sem codificação de saída ou sanitização adequadas. Um usuário autenticado com permissão para criar projetos pode armazenar um payload de JavaScript malicioso em um nome de projeto. Quando outro administrador abre posteriormente um editor de entidade contendo o seletor de projetos, o script malicioso é executado no navegador dele.
Propriedade Valor Produto Mautic Versões Afetadas 7.0.0 – 7.1.1 Versão Corrigida 7.1.2 Componente Project Selector Tipo de Vulnerabilidade Stored Cross-Site Scripting (XSS)
A aplicação armazena nomes de projetos fornecidos por usuários autenticados e posteriormente os recupera por meio de um endpoint AJAX. Ao renderizar o seletor de projetos, a aplicação insere esses valores diretamente no DOM como elementos HTML de opção, sem escapar ou sanitizar o conteúdo.
Conceitualmente:
User creates project
│
▼
Project name stored in database
│
▼
AJAX returns project name
│
▼
Inserted into DOM without sanitization
│
▼
Browser executes embedded JavaScript
Como a aplicação confia nos dados armazenados, o JavaScript malicioso é executado sempre que outro usuário privilegiado carrega a página vulnerável.
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
Um atacante com permissão para criar projetos cria um projeto cujo nome contém um payload de JavaScript malicioso.
Posteriormente, um administrador edita outra entidade que inclui o Project Selector. O seletor carrega os nomes dos projetos via AJAX e os insere diretamente na página. Como o nome do projeto não é sanitizado, o navegador executa o script incorporado com os privilégios do administrador.
Imagine que o Mautic tenha um formulário como este:
POST /projects/create HTTP/1.1
Content-Type: application/x-www-form-urlencoded
projectName=Marketing Campaign
description=Email Campaign
O projeto é salvo como:
Marketing Campaign
Etapa 2: O Atacante Cria um Projeto
Em vez de um nome normal, o atacante insere HTML contendo um 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/HEAD/x" onerror="console.log('XSS Demo')">
description=Test
O banco de dados agora armazena exatamente essa string.
Etapa 3: AJAX Retorna o Valor Armazenado
Posteriormente, um administrador abre uma página que carrega os projetos.
Resposta AJAX:
{
"id": 7,
"projectName": ""
}
Etapa 4: JavaScript Vulnerável
Suponha que a aplicação faça isso:
const project = response.projectName;
document.getElementById("projects").innerHTML +=
`<option>${project}</option>`;
O navegador vê:
<option>
<img src="https://raw.githubusercontent.com/aj2108/cve-2026-9811/HEAD/x" onerror="console.log('XSS Demo')">
</option>
Como a aplicação inseriu a string como HTML em vez de texto, o navegador a interpreta como um elemento real. A imagem não carrega (src="x"), fazendo com que o manipulador onerror seja executado.
A exploração bem-sucedida pode permitir que um atacante:
| Métrica | Pontuação |
|---|---|
| CVSS v3.1 (CNA) | 5.4 (Médio) |
O NVD ainda não publicou sua própria avaliação CVSS para este CVE.
Nota: O fornecedor não publicou o código-fonte vulnerável exato. O exemplo a seguir ilustra apenas o padrão da vulnerabilidade.
// Data returned from AJAX
const project = response.projectName;
// Unsafe: inserted directly into the DOM
document.getElementById("projectSelector").innerHTML +=
`<option>${project}</option>`;
O nome do projeto se origina da entrada do usuário, mas é inserido na página sem codificação HTML. Se o valor armazenado contiver HTML ou JavaScript, o navegador o interpreta como conteúdo executável em vez de texto simples.
const option = document.createElement("option");
// Safe: assign as text, not HTML
option.textContent = response.projectName;
document.getElementById("projectSelector").appendChild(option);
Ou, se a saída HTML for inevitável, garanta a codificação de saída adequada antes da inserção.
O uso de textContent (ou de uma API segura equivalente) garante que quaisquer caracteres especiais sejam tratados como texto simples em vez de HTML ou JavaScript executável. Mesmo que um nome de projeto malicioso seja armazenado no banco de dados, ele será exibido literalmente em vez de ser executado.