Skip to content
KitploitKITPLOIT
OutilsBlog
Log in
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2026-34212 — Docmost a accepté une URL javascript: à l'intérieur d'un attachment node, l'a préservée lors du stockage et du rendu, et l'a retransformée en une ancre cliquable dans l'origine de Docmost. | Kitploit
Outils/GitHubGitHub/0xmrma/cve-2026-34212
Analyse des VulnérabilitésExploitationSécurité WebTests d'IntrusionArticles et RechercheApprentissage et Éducation
GitHub0xmrma/cve-2026-34212

CVE-2026-34212

Docmost a accepté une URL javascript: à l'intérieur d'un attachment node, l'a préservée lors du stockage et du rendu, et l'a retransformée en une ancre cliquable dans l'origine de Docmost.

Voir le dépôt
4il y a 3 moisPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2026-34212

Docmost a accepté une URL de type javascript: dans un nœud de pièce jointe, l’a conservée lors du stockage et du rendu, et l’a transformée en un lien cliquable dans l’origine de Docmost.

Introduction

J’ai identifié, divulgué de manière responsable et reproduit un problème de stored XSS de sévérité élevée dans Docmost, la plateforme de documentation collaborative open-source.

Le site officiel de Docmost le présente comme un wiki interne prêt pour l’entreprise avec plus de 3 millions de téléchargements, et indique qu’il est utilisé par des équipes d’organisations telles que Vilnius City, Bechtle, le gouvernement australien, la Croix-Rouge et ETS Québec.

Le bogue se trouvait à un endroit facile à manquer dans les systèmes de texte enrichi :

pas dans l’extension de lien ordinaire, mais dans un type de nœud personnalisé distinct utilisé pour les pièces jointes.

Je passais en revue le pipeline de l’éditeur avec une question très précise en tête :

si les liens normaux bloquent les URLs javascript:, les nœuds de pièces jointes appliquent-ils la même règle avant d’atteindre un sink d’ancrage ?

Dans les versions vulnérables, ce n’était pas le cas.

Docmost acceptait un nœud de pièce jointe malveillant dans le JSON de la page, stockait son attribut url sans modification, puis rendait cette valeur sous la forme d’un élément <a href="javascript:..."> cliquable.

Ce problème est devenu CVE-2026-34212.

Docmost : docmost/docmost
Avis : GHSA-cf68-cff9-hq4w
CVE : CVE-2026-34212
Corrigé dans : v0.71.0

photo0

Chaîne d’attaque

URL du nœud de pièce jointe contrôlée par l’attaquant -> JSON de la page accepté et stocké sans modification -> rendu HTML/React transformant cette URL en href d’ancrage -> victime clique sur l’action de la pièce jointe -> JavaScript contrôlé par l’attaquant s’exécute dans l’origine de Docmost


Ce que fait cette partie de Docmost

Docmost stocke le contenu des pages dans un format JSON compatible avec ProseMirror/Tiptap.

Ce modèle de contenu inclut des nœuds de bloc personnalisés pour des éléments tels que :

  • images
  • diagrammes
  • intégrations
  • pièces jointes

Le nœud de pièce jointe stocke des champs comme :

  • url
  • name
  • mime
  • size
  • attachmentId

Le serveur accepte le contenu des pages dans plusieurs formats :

  • json
  • markdown
  • html

et le normalise en JSON ProseMirror avant de le stocker.

Cela signifie que tout type de nœud pouvant porter une URL fait partie d’une frontière de confiance directe.

Si l’un de ces types de nœuds finit par être rendu sous la forme d’un <a href>, la gestion des schémas d’URL n’est pas facultative. Elle fait partie du modèle de sécurité.


Pourquoi cette surface méritait d’être examinée

Les extensions d’éditeur personnalisées sont une source fréquente de dérive de sécurité.

Le système de base peut déjà savoir comment traiter correctement les URLs dangereuses, mais chaque nœud personnalisé doit réappliquer les mêmes règles à ses propres sinks.

Cela crée une stratégie de révision prévisible :

  • trouver chaque type de nœud qui stocke un champ de type URL
  • tracer où ce champ est accepté
  • tracer où ce champ est rendu
  • comparer son comportement de nettoyage avec celui du traitement normal des liens de la plateforme

C’est exactement ce qui a exposé ce bogue.

L’extension de lien normal de Docmost traitait déjà javascript: comme dangereux.

Son nœud de pièce jointe ne le faisait pas.

Une fois que vous voyez cette asymétrie, la question de sécurité devient évidente :

puis-je persister un nœud de pièce jointe dont l’url est javascript: et obtenir qu’il soit rendu sous forme d’ancrage actif ?

La réponse était oui.


Cause racine

La cause racine était un nettoyage d’URL incohérent entre les types de nœuds de contenu.

Le chemin de contenu côté serveur acceptait des URLs de pièces jointes arbitraires tant que le contenu global correspondait au schéma ProseMirror.

Dans la version vulnérable :

  • CreatePageDto acceptait content?: string | object
  • PageService.parseProsemirrorContent() normalisait markdown, html ou json
  • le serveur appelait ensuite jsonToNode(prosemirrorJson)
  • si la validation du schéma réussissait, le contenu était stocké

Cette étape de validation vérifiait la validité structurelle, pas la sécurité de l’URL.

La partie critique de la logique serveur vulnérable était effectivement :

prosemirrorJson = content;
jsonToNode(prosemirrorJson);
return prosemirrorJson;

Aucune normalisation de schéma d’URL de pièce jointe n’avait lieu ici.

Plus tard, l’extension de pièce jointe rendait directement la valeur contrôlée par l’attaquant.

Le nœud de pièce jointe vulnérable faisait ceci :

url: {
  default: "",
  parseHTML: (element) => element.getAttribute("data-attachment-url"),
  renderHTML: (attributes) => ({
    "data-attachment-url": attributes.url,
  }),
},

puis :

[
  "a",
  {
    href: HTMLAttributes["data-attachment-url"],
    class: "attachment",
    target: "blank",
  },
  `${HTMLAttributes["data-attachment-name"]}`,
]

Côté client, la vue de nœud React encapsulait cela à nouveau dans :

<a href={getFileUrl(url)} target="_blank">

Mais getFileUrl() ne traitait de manière spéciale que :

  • les URLs http absolues
  • /api/...
  • /files/...

Tout le reste était renvoyé sans modification.

Ainsi, une charge utile comme :

javascript:alert(document.domain)

survivait à :

  • stockage JSON
  • validation du schéma côté serveur
  • rendu HTML
  • gestion d’URL côté client

Cela seul serait déjà suffisant pour une XSS stockée.

Ce qui rend la cause racine particulièrement claire, c’est le point de comparaison.

L’extension de lien normal de Docmost bloquait explicitement javascript: :

  • elle rejetait javascript: dans parseHTML()
  • elle effaçait un href javascript: dans renderHTML()

Le produit savait donc déjà que ce schéma était dangereux.

Le nœud de pièce jointe n’a tout simplement pas appliqué la même politique.

Voilà pourquoi ce n’était pas une « XSS générique dans l’éditeur ».

C’était un écart de frontière de confiance propre à un nœud.


Pourquoi c’est un problème de sécurité, pas seulement un manque de nettoyage

Ce bogue ne concernait pas simplement une esthétique HTML dangereuse.

Il permettait à un attaquant capable de modifier une page de persister une charge utile malveillante qui s’exécuterait plus tard dans l’origine de Docmost lorsqu’un autre utilisateur interagirait avec la pièce jointe rendue.

Cela compte car un script dans l’origine peut :

  • lire les données auxquelles la victime a accès
  • envoyer des requêtes authentifiées en tant que victime
  • modifier le contenu que la victime est autorisée à modifier
  • abuser de toute surface DOM ou API exposée à la session

L’exigence d’un clic ne réduit pas cela à un problème trivial.

Le clic fait partie du comportement normal du produit : l’interface utilisateur présente intentionnellement la pièce jointe comme un lien/icône actionnable.

La question de sécurité n’est donc pas « l’attaquant peut-il forcer du JS arbitraire sans aucune interaction ? »

La vraie question est :

l’application stocke-t-elle du contenu porteur de script contrôlé par l’attaquant et le présente-t-elle ensuite à d’autres utilisateurs comme un chemin d’interaction de confiance ?

Dans les versions vulnérables, oui.

C’est une XSS stockée.


Pourquoi l’exploitation était pratique

Le chemin d’exploitation était simple :

Télécharger l’outil