Skip to content

Commit

Permalink
Merge pull request #2655 from mermaid-js/2646_handling
Browse files Browse the repository at this point in the history
2646 Removes a possible way for a diagram author to trigger a JavaScript using in diagram code.
  • Loading branch information
knsv authored Jan 22, 2022
2 parents 87dc133 + 3a2f665 commit e10bb77
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 11 deletions.
107 changes: 107 additions & 0 deletions cypress/platform/xss19.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-d3',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10,
curve: 'cardinal',
htmlLabels: true,
},
htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
// securityLevel: 'loose',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'],
// themeVariables: {relationLabelColor: 'red'}
});
function callback() {
alert('It worked');
}
function xssAttack() {
const div = document.createElement('div');
div.id = 'the-malware';
div.className = 'malware';
div.innerHTML = 'XSS Succeeded';
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}

var diagram = `classDiagram
class Shape{
<<<img/src='1'/`;

// // var diagram = "stateDiagram-v2\n";
diagram += `onerror=xssAttack()>>>
}`;
// diagram += '//via.placeholder.com/64\' width=64 />"]';
// console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
console.log(res);
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

10 changes: 5 additions & 5 deletions docs/directives.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
**Edit this Page** [![N|Solid](img/GitHub-Mark-32px.png)](https://github.com/mermaid-js/mermaid/blob/develop/docs/directives.md)

## Directives
Directives gives a diagram author the capability to alter the appearance of a diagram before rendering by changing the applied configuration.
Directives gives a diagram author the capability to alter the appearance of a diagram before rendering by changing the applied configuration.

Directives are divided into two sets or orders, by priority in parsing. The first set, containing 'init' or 'initialize' directives are loaded ahead of any other directive. While the other set, containing all other kinds of directives are parsed and factored into the rendering, only after 'init' and the desired graph-type are declared.

Expand All @@ -18,7 +18,7 @@ Directives are divided into two sets or orders, by priority in parsing. The firs
init would be an argument-directive: %%{init: { **insert argument here**}}%%

The json object that is passed as {**argument** } must be valid key value pairs and encased in quotation marks or it will be ignored.
Valid Key Value pairs can be found in config.
Valid Key Value pairs can be found in config.

The init/initialize directive is parsed earlier in the flow, this allows the incorporation of `%%init%%` directives into the mermaid diagram that is being rendered. Example:
```mmd
Expand All @@ -27,11 +27,11 @@ graph >
A-->B
```

will set the `logLevel` to `debug` and the `theme` to `dark` for a flowchart diagram, changing the appearance of the diagram itself.
will set the `logLevel` to `debug` and the `theme` to `dark` for a flowchart diagram, changing the appearance of the diagram itself.

Note: 'init' or 'initialize' are both acceptable as init directives. Also note that `%%init%%` and `%%initialize%%` directives will be grouped together after they are parsed. This means:

```mmd
```mmd2
%%{init: { 'logLevel': 'debug', 'theme': 'forest' } }%%
%%{initialize: { 'logLevel': 'fatal', "theme":'dark', 'startOnLoad': true } }%%
...
Expand Down Expand Up @@ -79,6 +79,6 @@ Init directives and any other non-multiline directives should be backwards compa

Multiline directives, however, will pose an issue and will render an error. This is unavoidable.

# example
# example


4 changes: 3 additions & 1 deletion src/dagre-wrapper/createLabel.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { select } from 'd3';
import { log } from '../logger'; // eslint-disable-line
import { getConfig } from '../config';
import { evaluate } from '../diagrams/common/common';
import { sanitizeText, evaluate } from '../diagrams/common/common';

const sanitizeTxt = (txt) => sanitizeText(txt, getConfig());

/**
* @param dom
Expand Down
10 changes: 6 additions & 4 deletions src/diagrams/class/classDb.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ let classCounter = 0;

let funs = [];

const sanitizeText = (txt) => common.sanitizeText(txt, configApi.getConfig());

export const parseDirective = function (statement, context, type) {
mermaidAPI.parseDirective(this, statement, context, type);
};
Expand Down Expand Up @@ -141,11 +143,11 @@ export const addMember = function (className, member) {

if (memberString.startsWith('<<') && memberString.endsWith('>>')) {
// Remove leading and trailing brackets
theClass.annotations.push(memberString.substring(2, memberString.length - 2));
theClass.annotations.push(sanitizeText(memberString.substring(2, memberString.length - 2)));
} else if (memberString.indexOf(')') > 0) {
theClass.methods.push(memberString);
theClass.methods.push(sanitizeText(memberString));
} else if (memberString) {
theClass.members.push(memberString);
theClass.members.push(sanitizeText(memberString));
}
}
};
Expand All @@ -161,7 +163,7 @@ export const cleanupLabel = function (label) {
if (label.substring(0, 1) === ':') {
return common.sanitizeText(label.substr(1).trim(), configApi.getConfig());
} else {
return label.trim();
return sanitizeText(label.trim());
}
};

Expand Down
4 changes: 3 additions & 1 deletion src/diagrams/class/classRenderer-v2.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ parser.yy = classDb;
let idCache = {};
const padding = 20;

const sanitizeText = (txt) => common.sanitizeText(txt, getConfig());

const conf = {
dividerMargin: 10,
padding: 5,
Expand Down Expand Up @@ -103,7 +105,7 @@ export const addClasses = function (classes, g) {
g.setNode(vertex.id, {
labelStyle: styles.labelStyle,
shape: _shape,
labelText: vertexText,
labelText: sanitizeText(vertexText),
classData: vertex,
rx: radious,
ry: radious,
Expand Down

0 comments on commit e10bb77

Please sign in to comment.