Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2026-34212 — O Docmost aceitou uma URL javascript: dentro de um nó de anexo, preservou-a através do armazenamento e renderização, e a transformou novamente em uma âncora clicável na origem do Docmost. | Kitploit
Ferramentas/GitHubGitHub/0xmrma/cve-2026-34212
Análise de VulnerabilidadesExploraçãoSegurança WebTestes de PenetraçãoPapers e PesquisaAprendizado e Educação
GitHub0xmrma/cve-2026-34212

CVE-2026-34212

O Docmost aceitou uma URL javascript: dentro de um nó de anexo, preservou-a através do armazenamento e renderização, e a transformou novamente em uma âncora clicável na origem do Docmost.

Ver Repositório
4há 3 mesesAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2026-34212

O Docmost aceitou uma URL javascript: dentro de um nó de anexo, preservou-a durante o armazenamento e a renderização, e a transformou novamente em um âncora clicável na origem do Docmost.

Introdução

Identifiquei, divulguei responsavelmente e reproduzi um problema de XSS armazenado de gravidade Alta no Docmost, a plataforma de documentação colaborativa de código aberto.

O site oficial do Docmost o apresenta como uma wiki on-premises pronta para empresas com mais de 3 milhões de downloads, e afirma ser confiável por equipes de organizações como Vilnius City, Bechtle, o Governo Australiano, a Cruz Vermelha e ETS Quebec.

O bug estava em um local fácil de passar despercebido em sistemas de texto rico:

não na extensão de link comum, mas em um tipo de nó personalizado separado usado para anexos de arquivos.

Estava revisando o pipeline do editor com uma pergunta muito específica em mente:

se links normais bloqueiam URLs javascript:, os nós de anexo aplicam a mesma regra antes de chegar a um sink de âncora?

Em versões vulneráveis, não aplicavam.

O Docmost aceitou um nó de anexo malicioso no JSON da página, armazenou seu atributo url inalterado e, posteriormente, renderizou esse valor de volta em um elemento <a href="javascript:..."> clicável.

Esse problema se tornou CVE-2026-34212.

Docmost: docmost/docmost
Advisory: GHSA-cf68-cff9-hq4w
CVE: CVE-2026-34212
Corrigido em: v0.71.0

photo0

Cadeia de Ataque

URL do nó de anexo controlada pelo atacante -> JSON da página aceito e armazenado inalterado -> Renderização HTML/React transforma essa URL em href de âncora -> vítima clica na ação do anexo -> JavaScript controlado pelo atacante é executado na origem do Docmost


O Que Esta Parte do Docmost Faz

O Docmost armazena o conteúdo da página em um formato JSON compatível com ProseMirror/Tiptap.

Esse modelo de conteúdo inclui nós de bloco personalizados para coisas como:

  • imagens
  • diagramas
  • embeds
  • anexos

O nó de anexo armazena campos como:

  • url
  • name
  • mime
  • size
  • attachmentId

O servidor aceita o conteúdo da página em vários formatos:

  • json
  • markdown
  • html

e o normaliza para JSON ProseMirror antes de armazená-lo.

Isso significa que qualquer tipo de nó que possa carregar uma URL faz parte de um limite de confiança direto.

Se um desses tipos de nó eventualmente renderizar em um <a href>, o tratamento de esquema de URL não é opcional. Faz parte do modelo de segurança.


Por Que Essa Superfície Valia a Pena Ser Analisada

Extensões de editor personalizadas são uma fonte frequente de desvio de segurança.

O sistema base já pode saber como lidar corretamente com URLs perigosas, mas cada nó personalizado ainda precisa reaplicar as mesmas regras em seus próprios sinks.

Isso cria uma estratégia de revisão previsível:

  • encontre cada tipo de nó que armazena um campo do tipo URL
  • rastreie onde esse campo é aceito
  • rastreie onde esse campo é renderizado
  • compare seu comportamento de sanitização com o tratamento de link normal da plataforma

Foi exatamente isso que expôs esse bug.

A extensão de link normal do Docmost já tratava javascript: como perigoso.

Seu nó de anexo não tratava.

Uma vez que você vê essa assimetria, a questão de segurança se torna óbvia:

posso persistir um nó de anexo cuja url seja javascript: e fazê-lo ser renderizado de volta em uma âncora viva?

A resposta foi sim.


Causa Raiz

A causa raiz foi sanitização inconsistente de URL entre tipos de nós de conteúdo.

O caminho de conteúdo do lado do servidor aceitava URLs de anexo arbitrárias, desde que o conteúdo geral correspondesse ao esquema ProseMirror.

Na versão vulnerável:

  • CreatePageDto aceitava content?: string | object
  • PageService.parseProsemirrorContent() normalizava markdown, html ou json
  • o servidor então chamava jsonToNode(prosemirrorJson)
  • se a validação do esquema passasse, o conteúdo era armazenado

Essa etapa de validação verificava a validade estrutural, não a segurança da URL.

A parte crítica da lógica vulnerável do servidor era efetivamente:

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

Nenhuma normalização de esquema de URL de anexo ocorria ali.

Posteriormente, a extensão de anexo renderizava o valor controlado pelo atacante diretamente.

O nó de anexo vulnerável fazia isso:

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

e depois:

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

No lado do cliente, a visualização do nó React envolvia isso novamente em:

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

Mas getFileUrl() só tratava casos especiais:

  • URLs http absolutas
  • /api/...
  • /files/...

Qualquer outra coisa era retornada inalterada.

Assim, um payload como:

javascript:alert(document.domain)

sobrevivia a:

  • armazenamento JSON
  • validação de esquema do lado do servidor
  • renderização HTML
  • tratamento de URL do lado do cliente

Isso por si só já seria suficiente para XSS armazenado.

O que torna a causa raiz especialmente clara é o ponto de comparação.

A extensão de link normal do Docmost bloqueava explicitamente javascript::

  • rejeitava javascript: em parseHTML()
  • zerava um href javascript: em renderHTML()

Portanto, o produto já sabia que esse esquema era perigoso.

O nó de anexo simplesmente falhou em aplicar a mesma política.

É por isso que isso não era "XSS genérico no editor."

Era uma lacuna de limite de confiança específica do nó.


Por Que Isso é um Problema de Segurança, Não Apenas Sanitização Ausente

Este bug não era meramente sobre estética HTML insegura.

Permitia que um atacante que pudesse editar uma página persistisse um payload malicioso que mais tarde seria executado na origem do Docmost quando outro usuário interagisse com o anexo renderizado.

Isso importa porque um script na origem pode:

  • ler dados que a vítima pode acessar
  • emitir requisições autenticadas como a vítima
  • modificar conteúdo que a vítima tem permissão para modificar
  • abusar de qualquer superfície DOM ou API exposta à sessão

A exigência de um clique não reduz isso a um problema trivial.

O clique faz parte do comportamento normal do produto: a interface apresenta intencionalmente o anexo como um link/ícone acionável.

Portanto, a questão de segurança não é "o atacante pode forçar JS arbitrário sem qualquer interação?"

A verdadeira questão é:

a aplicação armazena conteúdo malicioso contendo script controlado pelo atacante e posteriormente o apresenta a outros usuários como um caminho de interação confiável?

Em versões vulneráveis, sim.

Isso é XSS armazenado.


Por Que a Exploração Era Prática

O caminho de exploração era direto:

  • qualquer usuário com direitos de edição de página podia plantar o payload
  • a URL maliciosa sobrevivia ao armazenamento inalterada
  • a página era renderizada normalmente
  • os visualizadores só precisavam de acesso padrão à página
  • um clique na ação do anexo era suficiente para desencadear a execução

Isso também tornava usuários com privilégios mais altos alvos realistas.

Baixar ferramenta