Skip to content

Commit

Permalink
fix(xss)!: don't set popup content via innerHTML (#1275)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Titles are now interpreted literary, not as HTML. An
element has to be passed instead to get the same behavior (see the popup
example for details).
  • Loading branch information
Thomaash authored Jan 10, 2021
1 parent a96f2cf commit 57c0047
Show file tree
Hide file tree
Showing 27 changed files with 26,459 additions and 3,412 deletions.
8 changes: 0 additions & 8 deletions __snapshots__/test/package.test.ts.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,6 @@ exports['Package Exported files 1'] = {
" declarations/network/options.d.ts.map",
" declarations/network/shapes.d.ts",
" declarations/network/shapes.d.ts.map",
" declarations/shared/configurator-types.d.ts",
" declarations/shared/configurator-types.d.ts.map",
" declarations/shared/index.d.ts",
" declarations/shared/index.d.ts.map",
" dist/dist/vis-network.css",
" dist/dist/vis-network.min.css",
" dist/img/network/acceptDeleteIcon.png",
Expand Down Expand Up @@ -142,10 +138,6 @@ exports['Package Exported files 1'] = {
" dist/types/network/options.d.ts.map",
" dist/types/network/shapes.d.ts",
" dist/types/network/shapes.d.ts.map",
" dist/types/shared/configurator-types.d.ts",
" dist/types/shared/configurator-types.d.ts.map",
" dist/types/shared/index.d.ts",
" dist/types/shared/index.d.ts.map",
" dist/vis-network.esm.js",
" dist/vis-network.esm.js.map",
" dist/vis-network.esm.min.js",
Expand Down
169 changes: 169 additions & 0 deletions examples/network/other/popups.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Vis Network | Other | Popups</title>

<style type="text/css">
html,
body,
#mynetwork {
margin: 0px;
padding: 0px;
}

#mynetwork {
position: fixed;
left: 0px;
top: 0px;
bottom: 0px;
right: 50%;
min-height: 100vh;
border-right: 1px solid lightgray;
background: white;
}

#text {
position: absolute;
left: 50%;
padding: 1em;
}

#title {
margin-bottom: 5em;
}
</style>

<script
type="text/javascript"
src="https://unpkg.com/vis-data@latest/peer/umd/vis-data.min.js"
></script>
<script
type="text/javascript"
src="../../../peer/umd/vis-network.min.js"
></script>
<link
rel="stylesheet"
type="text/css"
href="../../../styles/vis-network.min.css"
/>
</head>

<body>
<div id="text">
<div id="title">
<h1>Vis Network</h1>
<h2>Other</h2>
<h3>Popups</h3>
</div>

<p>Both nodes and edges can have popup shown when hovered by a cursor.</p>

<p>It is possible to use plain text:</p>
<pre><code>
const nodes = [{
id: 1,
title: "Popup text",
}];
</code></pre>

<p>Alternatively an element can be supplied:</p>
<pre><code>
const element = document.createElement("div");
// Add child nodes, change styles…

const nodes = [{
id: 1,
title: element,
}];
</code></pre>

<h4>XSS</h4>
<p>
In the past the popup was filled using innerHTML. It is still possible
to achieve similar behavior via an element.
</p>
<pre><code>
function createHTMLTitle(html) {
var element = document.createElement("div");
element.innerHTML = html;
return element;
}
</code></pre>
<p>
Keep in mind though that this can lead to XSS attacks:
<input type="button" onclick="addXSSNode()" value="add XSS node." />
</p>
</div>

<div id="mynetwork"></div>
<script id="code-src" type="text/javascript">
// You can supply an element as your title.
var titleElement = document.createElement("div");
titleElement.style.border = "1px solid gray";
titleElement.style.height = "10em";
titleElement.style.width = "10em";

// With arbitrary DOM structure underneath.
var titleElementInner = document.createElement("div");
titleElementInner.style.height = "1em";
titleElementInner.style.width = "1em";
titleElementInner.style.background = "red";
titleElementInner.style.transition = "all 1s ease-in-out";
titleElement.appendChild(titleElementInner);

// Even dynamic behavior is possible.
setInterval(function () {
titleElementInner.style.marginTop = Math.random() * 9 + "em";
titleElementInner.style.marginLeft = Math.random() * 9 + "em";
}, 2000);

var nodes = new vis.DataSet([
{
id: 1,
label: "Text",
title:
"Plain text with no chance of <script>alert('XSS')</scr" + "ipt>!",
},
{ id: 2, label: "Element", title: titleElement },
]);

var edges = new vis.DataSet([
{ from: 1, to: 2, title: "Edges work exactly the same." },
]);

// Instantiate our network object.
var container = document.getElementById("mynetwork");
var data = {
nodes: nodes,
edges: edges,
};
var options = {
nodes: {
shape: "dot",
},
};
network = new vis.Network(container, data, options);

// You can use the element to process HTML and execute JavaScript.
function createHTMLTitle(html) {
var element = document.createElement("div");
element.innerHTML = html;
return element;
}

// You can run this function by clicking the “add XSS node” button above.
function addXSSNode() {
nodes.add({
label: "XSS",
title: createHTMLTitle(
"HTML with a chance of " +
'<script>alert("Up to the specs, scripts shouldn\'t execute.");</scr' +
"ipt>" +
'<img src="But that doesn\'t mean you\'re safe!" onerror="alert(\'You\\\'ve been hacked, muhehehe!\');" alt="XSS" />.'
),
});
}
</script>
</body>
</html>
2 changes: 1 addition & 1 deletion lib/index-legacy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export { data };
export { DataSet, DataView, Queue } from "vis-data/esnext";

// bundled external libraries
import { Hammer } from "./shared";
import { Hammer } from "vis-util/esnext";
export { Hammer };
import * as keycharm from "keycharm";
export { keycharm };
13 changes: 10 additions & 3 deletions lib/network/Network.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
// Load custom shapes into CanvasRenderingContext2D
import "./shapes";

import "vis-util/esnext/styles/activator.css";
import "vis-util/esnext/styles/bootstrap.css";
import "vis-util/esnext/styles/color-picker.css";
import "vis-util/esnext/styles/configurator.css";
import "vis-util/esnext/styles/popup.css";

import Emitter from "component-emitter";
import {
Activator,
Configurator,
VALIDATOR_PRINT_STYLE,
Validator,
deepExtend,
recursiveDOMDelete,
selectiveDeepExtend,
} from "vis-util/esnext";
import { DOTToGraph } from "./dotparser";
import { parseGephi } from "./gephiParser";
import { Activator } from "../shared";
import * as locales from "./locales";
import { normalizeLanguageCode } from "./locale-utils";

Expand All @@ -26,8 +35,6 @@ import InteractionHandler from "./modules/InteractionHandler";
import SelectionHandler from "./modules/SelectionHandler";
import LayoutEngine from "./modules/LayoutEngine";
import ManipulationSystem from "./modules/ManipulationSystem";
import { Configurator } from "../shared";
import { VALIDATOR_PRINT_STYLE, Validator } from "../shared";
import {
allOptions,
configureOptions,
Expand Down
2 changes: 1 addition & 1 deletion lib/network/modules/Canvas.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Hammer } from "../../shared";
import { onRelease, onTouch } from "../../hammerUtil";

import {
Hammer,
addEventListener,
removeEventListener,
selectiveDeepExtend,
Expand Down
2 changes: 1 addition & 1 deletion lib/network/modules/InteractionHandler.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {
Popup,
getAbsoluteLeft,
getAbsoluteTop,
mergeOptions,
parseColor,
selectiveNotDeepExtend,
} from "vis-util/esnext";
import NavigationHandler from "./components/NavigationHandler";
import { Popup } from "../../shared";

/**
* Handler for interactions
Expand Down
2 changes: 1 addition & 1 deletion lib/network/modules/LayoutEngine.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"use strict";
import TimSort from "timsort";
import {
Alea,
deepExtend,
forEach,
mergeOptions,
Expand All @@ -46,7 +47,6 @@ import {
fillLevelsByDirectionLeaves,
fillLevelsByDirectionRoots,
} from "./layout-engine";
import { Alea } from "vis-util/esnext";

/**
* Container for derived data on current network, relating to hierarchy.
Expand Down
3 changes: 1 addition & 2 deletions lib/network/modules/ManipulationSystem.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import "./ManipulationSystem.css";

import { deepExtend, recursiveDOMDelete } from "vis-util/esnext";
import { Hammer, deepExtend, recursiveDOMDelete } from "vis-util/esnext";
import { v4 as randomUUID } from "uuid";
import { Hammer } from "../../shared";
import { onTouch } from "../../hammerUtil";

/**
Expand Down
2 changes: 1 addition & 1 deletion lib/network/modules/components/NavigationHandler.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import "./NavigationHandler.css";

import { Hammer } from "../../../shared";
import { Hammer } from "vis-util/esnext";
import { onRelease, onTouch } from "../../../hammerUtil";
import keycharm from "keycharm";

Expand Down
2 changes: 1 addition & 1 deletion lib/network/modules/components/Node.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
VALIDATOR_PRINT_STYLE,
bridgeObject,
fillIfDefined,
mergeOptions,
Expand All @@ -25,7 +26,6 @@ import Star from "./nodes/shapes/Star";
import Text from "./nodes/shapes/Text";
import Triangle from "./nodes/shapes/Triangle";
import TriangleDown from "./nodes/shapes/TriangleDown";
import { VALIDATOR_PRINT_STYLE } from "../../../shared";

/**
* A node. A node can be connected to other nodes via one or multiple edges.
Expand Down
2 changes: 1 addition & 1 deletion lib/network/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
ConfiguratorConfig,
ConfiguratorHideOption,
OptionsConfig,
} from "../shared";
} from "vis-util/esnext";

/**
* This object contains all possible options. It will check if the types are correct, if required if the option is one
Expand Down
14 changes: 0 additions & 14 deletions lib/shared/activator.css

This file was deleted.

Loading

0 comments on commit 57c0047

Please sign in to comment.