Zum Inhalt springen

Sicherheit ​

Pivotick läuft vollständig im Browser: Es gibt keinen Server, keine Sitzung und keine eigene Persistenz. Die Grenze, die zählt, ist die zwischen Ihren Diagrammdaten und dem DOM Ihrer Seite – Pivotick rendert die Daten, die Sie übergeben, in das Dokument, das Ihrer Anwendung gehört.

Wenn diese Daten von einem Ort stammen, den Sie nicht vollständig kontrollieren können – einem Feed mit Informationen zu Bedrohungen, einem CVE-Spiegel, einem importierten Datensatz oder dem Upload eines anderen Benutzers – behandeln Sie sie als nicht vertrauenswürdig und lesen Sie den Rest dieser Seite.

Was Pivotick garantiert ​

Alles, was die Bibliothek aus Ihren Daten rendert, wird als Text eingefügt, nicht als Markup. Dazu gehören Knoten- und Kantenbeschriftungen, Beschreibungen, IDs, Eigenschaftsschlüssel und -werte sowie Notizinhalte:

  • Beschriftungen, Beschreibungen und Eigenschaftsnamen/-werte werden mit textContent geschrieben.
  • Der Notizinhalt ist Markdown, wird mit marked gerendert und dann mit DOMPurify anhand einer Zulassungsliste der von Markdown selbst erstellten Tags bereinigt. <style>, die Formularelemente und Inline-Attribute style sind nicht darauf.
  • style.svgIcon-Markup wird bereinigt (SVG-Profil), bevor es das Dokument erreicht, daher werden die Ereignishandler <script> und <foreignObject> sowie <style> und <a> entfernt. Ein Inline-<style> ist nicht auf das Symbol beschränkt und ein <a> würde die Auswahl des Knotens in eine Navigation umwandeln. Die verbleibenden Attribute sind die SVG-Zulassungsliste von DOMPurify sowie dominant-baseline und alignment-baseline, sodass Text auf die gleiche Weise zentriert werden kann wie Pivotick seine eigenen Glyphen. <use> wurde komplett entfernt, also Inline-Sprite-Symbole, anstatt auf sie zu verweisen.
  • style.imagePath ist auf die Schemata http:, https:, data: und blob: beschränkt.
  • Farben aus den Daten, die style.color eines Knotens und die color einer Notiz, müssen als CSS-Farben analysiert werden, bevor sie das Dokument erreichen, sodass sie kein url() in ein background schmuggeln können.
  • Als Links gerenderte Eigenschaftswerte tragen rel="noopener noreferrer", und alle Werte, die Ihren Ursprung verlassen, einschließlich //host/path, werden in einem neuen Tab geöffnet, anstatt Ihren zu ersetzen.

Ein string wird daher immer als Text gerendert. Überall dort, wo eine Option string | HTMLElement akzeptiert, erhalten Sie durch die Rückgabe einer Zeichenfolge Text; Um Ihr eigenes HTML zu rendern, erstellen Sie ein HTMLElement und geben Sie es zurück:

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
} }

Geändert in 1.4.0 / 1.5.0

Frühere Versionen analysierten Zeichenfolgen wie HTML – Eigenschaftswerte in 1.3.0 und früher, alle anderen string | HTMLElement-Optionen (zusätzliche Panels, Kontextmenüeinträge, benutzerdefinierte Renderer) bis 1.4.0. Wenn Sie sich darauf verlassen haben, um Markup einzufügen, wechseln Sie zur Rückgabe eines Elements.

Trusted-HTML sinkt ​

Es gibt einige spezielle Optionen, mit denen Sie Ihr eigenes Markup bereitstellen können. Pivotick fügt ein, was Sie ihm wörtlich geben, also erstellen Sie diese niemals aus nicht vertrauenswürdigen Daten:

OptionWo
rawHeader / rawBodyModal und SlidePanel Optionen
render.defaultNodeStyle.htmlKnoteninhalte in einem <foreignObject> gezeichnet

Wenn Sie Daten in einem dieser Elemente benötigen, fügen Sie diese mit textContent in ein von Ihnen erstelltes Element ein, anstatt sie in eine Markup-Zeichenfolge zu interpolieren:

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 })

Ausgehende Anfragen ​

Knoten können über style.imagePath oder ein <image href> in style.svgIcon auf Bilder verweisen. Durch das Rendern eines solchen Knotens rufen die Browser Ihrer Benutzer diese URL ab. Wenn die URL aus nicht vertrauenswürdigen Daten stammt, erfährt der Autor, dass das Diagramm angezeigt wurde, zusammen mit der IP-Adresse des Betrachters, dem Zeitpunkt und User-Agent – einem Tracking-Pixel.

Schema-Einschränkungen können dies nicht verhindern, da https: zugelassen sein muss, damit die Funktion überhaupt funktioniert. Wenn Ihre Daten nicht vertrauenswürdig sind und dies für Sie von Bedeutung ist, entfernen Sie entweder die Bildreferenzen, bevor Sie die Daten weitergeben, oder schreiben Sie sie neu, oder schränken Sie sie durch eine Inhaltssicherheitsrichtlinie ein.

Pivotick benötigt kein eval und kein Inline-<script>, daher funktioniert es unter einer strengen Richtlinie. Ein CSP ist der kostengünstigste Weg, jede Injektion abzuschwächen – in der Bibliothek, in Ihrem eigenen Code oder in einer anderen Abhängigkeit:

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 ohne 'unsafe-inline' neutralisiert injizierte Event-Handler.
  • img-src Hier legen Sie fest, von welchen Host-Knotenbildern stammen können.
  • form-action-Grenzen, an denen jedes injizierte Formular posten könnte, unabhängig davon, was action sagt.
  • style-src 'unsafe-inline' ist derzeit erforderlich: Der Renderer legt Inline-Stile fest und das Stylesheet von Pivotick wird normalerweise von Ihrem Bundler eingefügt. Stellen Sie die CSS als Datei bereit und verwenden Sie eine Nonce oder einen Hash, wenn Sie sie löschen müssen.

Eine Schwachstelle melden ​

Bitte melden Sie vermutete Schwachstellen über GitHub Sicherheitshinweise und nicht über eine öffentliche Ausgabe.