
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 est une vulnérabilité de Cross-Site Scripting stocké (XSS stocké) affectant Mautic 7 (versions 7.0.0 à 7.1.1). La vulnérabilité existe dans le composant Project Selector, où les noms de projets renvoyés via une requête AJAX sont insérés dans la page sans encodage de sortie ni assainissement appropriés. Un utilisateur authentifié disposant de la permission de créer des projets peut stocker une charge utile JavaScript malveillante dans le nom d'un projet. Lorsqu'un autre administrateur ouvre ensuite un éditeur d'entité contenant le sélecteur de projet, le script malveillant s'exécute dans son navigateur.
Propriété Valeur Produit Mautic Versions concernées 7.0.0 – 7.1.1 Version corrigée 7.1.2 Composant Project Selector Type de vulnérabilité Cross-Site Scripting stocké (XSS)
L'application stocke les noms de projets fournis par des utilisateurs authentifiés puis les récupère ultérieurement via un point de terminaison AJAX. Lors du rendu du sélecteur de projet, l'application insère ces valeurs directement dans le DOM sous forme d'éléments d'option HTML sans échapper ni assainir le contenu.
Conceptuellement :
User creates project
│
▼
Project name stored in database
│
▼
AJAX returns project name
│
▼
Inserted into DOM without sanitization
│
▼
Browser executes embedded JavaScript
Comme l'application accorde sa confiance aux données stockées, du JavaScript malveillant s'exécute dès qu'un autre utilisateur privilégié charge la page vulnérable.
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 attaquant disposant de la permission de créer des projets crée un projet dont le nom contient une charge utile JavaScript malveillante.
Ensuite, un administrateur modifie une autre entité incluant le Project Selector. Le sélecteur charge les noms de projets via AJAX et les insère directement dans la page. Comme le nom du projet n'est pas assaini, le navigateur exécute le script intégré avec les privilèges de l'administrateur.
Imaginons que Mautic dispose d'un formulaire comme celui-ci :
POST /projects/create HTTP/1.1
Content-Type: application/x-www-form-urlencoded
projectName=Marketing Campaign
description=Email Campaign
Le projet est enregistré comme suit :
Marketing Campaign
Étape 2 : L'attaquant crée un projet
Au lieu d'un nom normal, l'attaquant saisit du HTML contenant un événement JavaScript inoffensif :
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
La base de données stocke désormais exactement cette chaîne.
Étape 3 : AJAX renvoie la valeur stockée
Plus tard, un administrateur ouvre une page qui charge des projets.
Réponse AJAX :
{
"id": 7,
"projectName": ""
}
Étape 4 : JavaScript vulnérable
Supposons que l'application fasse ceci :
const project = response.projectName;
document.getElementById("projects").innerHTML +=
`<option>${project}</option>`;
Le navigateur voit :
<option>
<img src="https://raw.githubusercontent.com/aj2108/cve-2026-9811/HEAD/x" onerror="console.log('XSS Demo')">
</option>
Comme l'application a inséré la chaîne en tant que HTML plutôt que texte, le navigateur l'analyse comme un véritable élément . L'image ne parvient pas à se charger (src="x"), ce qui déclenche l'exécution du gestionnaire onerror.
Une exploitation réussie peut permettre à un attaquant de :
| Métrique | Score |
|---|---|
| CVSS v3.1 (CNA) | 5.4 (Medium) |
La NVD n'a pas encore publié sa propre évaluation CVSS pour cette CVE.
Remarque : L'éditeur n'a pas publié le code source vulnérable exact. L'exemple suivant illustre uniquement le schéma de la vulnérabilité.
// Data returned from AJAX
const project = response.projectName;
// Unsafe: inserted directly into the DOM
document.getElementById("projectSelector").innerHTML +=
`<option>${project}</option>`;
Le nom du projet provient d'une saisie utilisateur mais est inséré dans la page sans encodage HTML. Si la valeur stockée contient du HTML ou du JavaScript, le navigateur l'interprète comme du contenu exécutable au lieu de texte brut.
const option = document.createElement("option");
// Safe: assign as text, not HTML
option.textContent = response.projectName;
document.getElementById("projectSelector").appendChild(option);
Ou, si la sortie HTML est inévitable, assurez un encodage de sortie approprié avant l'insertion.
L'utilisation de textContent (ou d'une API sécurisée équivalente) garantit que les caractères spéciaux sont traités comme du texte brut plutôt que comme du HTML ou du JavaScript exécutable. Même si un nom de projet malveillant est stocké dans la base de données, il sera affiché littéralement au lieu d'être exécuté.