Pular para o conteúdo

Segurança ​

Pivotick roda inteiramente no navegador: não há servidor, nem sessão e nem persistência própria. O limite que importa é aquele entre seus dados do gráfico e o DOM da sua página — Pivotick renderiza os dados que você entrega no documento que seu aplicativo possui.

Se esses dados vierem de algum lugar que você não controla totalmente – um feed de informações sobre ameaças, um espelho CVE, um conjunto de dados importado, upload de outro usuário – trate-os como não confiáveis e leia o restante desta página.

O que Pivotick garante ​

Tudo o que a biblioteca renderiza a partir dos seus dados é inserido como text, não como marcação. Isso abrange rótulos de nós e bordas, descrições, ids, chaves e valores de propriedades e conteúdo de notas:

  • Rótulos, descrições e nomes/valores de propriedades são escritos com textContent.
  • O conteúdo da nota é Markdown, renderizado com marked e depois higienizado com DOMPurify em relação a uma lista de permissões das tags que o próprio Markdown produz. <style>, os elementos do formulário e os atributos style embutidos não estão nele.
  • A marcação style.svgIcon é higienizada (perfil SVG) antes de chegar ao documento, portanto, os manipuladores de eventos <script> e <foreignObject> são removidos, assim como <style> e <a>. Um <style> embutido não tem como escopo o ícone, e um <a> transformaria a seleção do nó em uma navegação. Os atributos que sobrevivem são a lista de permissões SVG do DOMPurify mais dominant-baseline e alignment-baseline, para que o texto possa ser centralizado da mesma forma que Pivotick centraliza seus próprios glifos. <use> é removido imediatamente, portanto, símbolos de sprite embutidos em vez de referenciá-los.
  • style.imagePath está restrito aos esquemas http:, https:, data: e blob:.
  • As cores dos dados, style.color de um nó e color de uma nota, devem ser analisadas como CSS cores antes de chegarem ao documento, portanto, não podem contrabandear um url() para um background.
  • Os valores de propriedade renderizados como links carregam rel="noopener noreferrer", e qualquer um que saia de sua origem, incluindo //host/path, abre em uma nova guia em vez de substituir a sua.

Portanto, um string sempre é renderizado como texto. Sempre que uma opção aceita string | HTMLElement, retornar uma string fornece texto; para renderizar seu próprio HTML, construa e retorne um HTMLElement:

ts
// Renders the literal characters "<b>hi</b>"
propertiesPanel: { render: () => '<b>hi</b>' }

// Renders bold text
propertiesPanel: { render: () => {
    const el = document.createElement('b')
    el.textContent = 'hi'
    return el
} }

Alterado em 1.4.0/1.5.0

Versões anteriores analisavam strings como HTML — valores de propriedade em 1.3.0 e anteriores, todas as outras opções string | HTMLElement (painéis extras, entradas de menu de contexto, renderizadores personalizados) até 1.4.0. Se você estava confiando nisso para injetar marcação, mude para o retorno de um elemento.

Pias HTML confiáveis ​

Existem algumas opções especificamente para que você possa fornecer sua própria marcação. Pivotick insere o que você fornece verbatim, então nunca construa estes a partir de dados não confiáveis:

OpçãoOnde
rawHeader / rawBodyOpções Modal e SlidePanel
render.defaultNodeStyle.htmlconteúdo do nó desenhado em um <foreignObject>

Se você precisar de dados dentro de um deles, coloque-os com textContent em um elemento que você criou, em vez de interpolá-los em uma string de marcação:

ts
// Unsafe: node.data.label lands in innerHTML
uiManager.createModal({ rawBody: true, body: `<h1>${node.getData().label}</h1>` })

// Safe
const title = document.createElement('h1')
title.textContent = node.getData().label
uiManager.createModal({ body: title })

Solicitações de saída ​

Os nós podem fazer referência a imagens, via style.imagePath ou um <image href> dentro de style.svgIcon. A renderização de tal nó faz com que os navegadores dos usuários busquem esse URL. Se o URL vier de dados não confiáveis, quem o escreveu saberá que o gráfico foi visualizado, juntamente com o endereço IP do visualizador, o tempo e User-Agent — um pixel de rastreamento.

As restrições do esquema não podem impedir isso, porque https: deve ser permitido para que o recurso funcione. Se seus dados não forem confiáveis ​​e isso for importante para você, remova/reescreva as referências de imagem antes de entregar os dados ou restrinja-os com uma Política de Segurança de Conteúdo.

Pivotick não precisa de eval nem de <script> embutido, portanto funciona sob uma política estrita. Um CSP é a maneira mais barata de atenuar qualquer injeção — na biblioteca, em seu próprio código ou em outra dependência:

Content-Security-Policy:
    default-src 'self';
    script-src 'self';
    img-src 'self' data: blob: https://images.example.com;
    style-src 'self' 'unsafe-inline';
    form-action 'self';
  • script-src sem 'unsafe-inline' é o que neutraliza os manipuladores de eventos injetados.
  • img-src é onde você determina de onde as imagens dos nós de hosts podem vir.
  • form-action limites onde qualquer formulário injetado poderia postar, seja lá o que for action diz.
  • style-src 'unsafe-inline' é atualmente necessário: o renderizador define estilos embutidos e a folha de estilo de Pivotick normalmente é injetada pelo seu empacotador. Sirva o CSS como um arquivo e use um nonce ou hash se precisar eliminá-lo.

Relatando uma vulnerabilidade ​

Por favor, relate suspeitas de vulnerabilidades através de GitHub avisos de segurança em vez de um problema público.