e2e test for stricter security in mermaid
122
dist/xssi.html
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>Mermaid Quick Test Page</title>
|
||||
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=">
|
||||
<script>
|
||||
function xss(x){
|
||||
alert(x + ' cause an xss attack');
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="mermaid">
|
||||
gantt
|
||||
title Exclusive end dates <strong>If bold then xss</strong> (Manual date should end on 3d)
|
||||
dateFormat YYYY-MM-DD
|
||||
axisFormat %d
|
||||
section Section1
|
||||
2 Days: 1, 2019-01-01,2d
|
||||
Manual Date: 2, 2019-01-01,2019-01-03
|
||||
</div>
|
||||
<img src=xss.png />
|
||||
<div class="mermaid">
|
||||
graph TD
|
||||
A["<strong>If bold then xss</strong>Christmas"] -->|Get <strong>If bold then xss</strong> money| B(Go <strong>If bold then xss</strong> shopping)
|
||||
B --> C{Let me thinksssss<br/>ssssssssssssssssssssss<br />sssssssssssssssssssssssssss}
|
||||
C -->|One| D[Laptop]
|
||||
C -->|Two| E[iPhone]
|
||||
C -->|Three| F[Car]
|
||||
</div>
|
||||
<div class="mermaid">
|
||||
graph TB
|
||||
subgraph "<strong>If bold then xss</strong>"
|
||||
a1-->a2
|
||||
end
|
||||
</div>
|
||||
<div class="mermaid">
|
||||
graph TD
|
||||
A[Christmas] -->|Get money| B(Go shopping)
|
||||
B --> C{Let me think}
|
||||
C -->|One| D[Laptop]
|
||||
C -->|Two| E[iPhone]
|
||||
C -->|Three| F[Car]
|
||||
click A "index.html#link-clicked" "link test"
|
||||
click B testClick "click test"
|
||||
classDef someclass fill:#f96;
|
||||
class A someclass;
|
||||
</div>
|
||||
|
||||
<div class="mermaid">
|
||||
sequenceDiagram
|
||||
participant "Alice"
|
||||
participant Bob
|
||||
participant John as John<br/>Second Line
|
||||
Alice ->> Bob: Hello Bob, how are you?
|
||||
Bob-->>John: How about you <strong>If bold then xss</strong>John?
|
||||
Bob--x Alice: I am good thanks!
|
||||
Bob-x John: I am good thanks!
|
||||
Note right of John: Bob thinks a long<br/>long time, so long<br/>that the text does<br/>not fit on a row.
|
||||
Bob-->Alice: Checking with John...
|
||||
alt either this
|
||||
Alice->>John: Yes
|
||||
else or this
|
||||
Alice->>John: No
|
||||
else or this will happen
|
||||
Alice->John: Maybe
|
||||
end
|
||||
par this happens in parallel
|
||||
Alice -->> Bob: Parallel message 1
|
||||
and
|
||||
Alice -->> John: Parallel message 2
|
||||
end
|
||||
</div>
|
||||
|
||||
<div class="mermaid">
|
||||
classDiagram
|
||||
Class01 <|-- AveryLongClass : Co<strong>If bold then xss</strong>ol
|
||||
Class03 "0" *-- "0..n" Class04
|
||||
Class05 "1" o-- "many" Class06
|
||||
Class07 .. Class08
|
||||
Class09 "many" --> "1" C2 : Where am i?
|
||||
Class09 "0" --* "1..n" C3
|
||||
Class09 --|> Class07
|
||||
Class07 : equals()
|
||||
Class07 : Object[] elementData
|
||||
Class01 : size()
|
||||
Class01 : int chimp
|
||||
Class01 : int gorilla
|
||||
Class08 <--> C2: Cool label
|
||||
</div>
|
||||
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>
|
||||
mermaid.initialize({
|
||||
theme: 'forest',
|
||||
// themeCSS: '.node rect { fill: red; }',
|
||||
logLevel: 3,
|
||||
flowchart: { curve: 'linear' },
|
||||
gantt: { axisFormat: '%m/%d/%Y' },
|
||||
sequence: { actorMargin: 50 },
|
||||
// sequenceDiagram: { actorMargin: 300 } // deprecated
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
function ganttTestClick(a, b, c){
|
||||
console.log("a:", a)
|
||||
console.log("b:", b)
|
||||
console.log("c:", c)
|
||||
}
|
||||
function testClick(nodeId) {
|
||||
console.log("clicked", nodeId)
|
||||
var originalBgColor = document.querySelector('body').style.backgroundColor
|
||||
document.querySelector('body').style.backgroundColor = 'yellow'
|
||||
setTimeout(function() {
|
||||
document.querySelector('body').style.backgroundColor = originalBgColor
|
||||
}, 100)
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,19 +1,23 @@
|
||||
/* eslint-env jest */
|
||||
import { Base64 } from 'js-base64'
|
||||
|
||||
export const mermaidUrl = (graphStr, options) => {
|
||||
export const mermaidUrl = (graphStr, options, api) => {
|
||||
const obj = {
|
||||
code: graphStr,
|
||||
mermaid: options
|
||||
}
|
||||
const objStr = JSON.stringify(obj)
|
||||
// console.log(Base64)
|
||||
return 'http://localhost:9000/e2e.html?graph=' + Base64.encodeURI(objStr)
|
||||
let url = 'http://localhost:9000/e2e.html?graph=' + Base64.encodeURI(objStr)
|
||||
if (api) {
|
||||
url = 'http://localhost:9000/xss.html?graph=' + graphStr
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
export const imgSnapshotTest = async (page, graphStr, options) => {
|
||||
export const imgSnapshotTest = async (page, graphStr, options, api) => {
|
||||
return new Promise(async resolve => {
|
||||
const url = mermaidUrl(graphStr, options)
|
||||
const url = mermaidUrl(graphStr, options, api)
|
||||
|
||||
await page.goto(url)
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Base64 } from 'js-base64'
|
||||
import mermaid from '../../dist/mermaid.core'
|
||||
|
||||
/**
|
||||
* ##contentLoaded
|
||||
@ -22,6 +23,29 @@ const contentLoaded = function () {
|
||||
global.mermaid.init()
|
||||
}
|
||||
}
|
||||
const contentLoadedApi = function () {
|
||||
let pos = document.location.href.indexOf('?graph=')
|
||||
if (pos > 0) {
|
||||
pos = pos + 7
|
||||
const graphBase64 = document.location.href.substr(pos)
|
||||
const graphObj = JSON.parse(Base64.decode(graphBase64))
|
||||
// const graph = 'hello'
|
||||
console.log(graphObj)
|
||||
const div = document.createElement('div')
|
||||
div.id = 'block'
|
||||
div.className = 'mermaid'
|
||||
// div.innerHTML = graphObj.code
|
||||
document.getElementsByTagName('body')[0].appendChild(div)
|
||||
global.mermaid.initialize(graphObj.mermaid)
|
||||
console.log('apa')
|
||||
|
||||
mermaid.render('newid', graphObj.code, (svgCode, bindFunctions) => {
|
||||
div.innerHTML = svgCode
|
||||
|
||||
bindFunctions(div)
|
||||
}, div)
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof document !== 'undefined') {
|
||||
/*!
|
||||
@ -30,7 +54,12 @@ if (typeof document !== 'undefined') {
|
||||
window.addEventListener(
|
||||
'load',
|
||||
function () {
|
||||
contentLoaded()
|
||||
if (this.location.href.match('xss.html')) {
|
||||
this.console.log('Using api')
|
||||
contentLoadedApi()
|
||||
} else {
|
||||
contentLoaded()
|
||||
}
|
||||
},
|
||||
false
|
||||
)
|
||||
|
44
e2e/platform/xss.html
Normal file
@ -0,0 +1,44 @@
|
||||
<html>
|
||||
<head>
|
||||
<script src="/e2e.js"></script>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<style>
|
||||
.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>
|
||||
<script>
|
||||
function xssAttack(){
|
||||
const div = document.createElement('div')
|
||||
div.id = 'the-malware'
|
||||
div.className = 'malware'
|
||||
div.innerHTML = 'XSS Succeeded'
|
||||
document.getElementsByTagName('body')[0].appendChild(div)
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<script src="./mermaid.js"></script>
|
||||
<script>
|
||||
mermaid.initialize({
|
||||
startOnLoad: false,
|
||||
useMaxWidth: true,
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
BIN
e2e/platform/xss.png
Normal file
After Width: | Height: | Size: 6.3 KiB |
After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 14 KiB |
15
e2e/spec/xss.spec.js
Normal file
@ -0,0 +1,15 @@
|
||||
/* eslint-env jest */
|
||||
import { imgSnapshotTest } from '../helpers/util.js'
|
||||
const { toMatchImageSnapshot } = require('jest-image-snapshot')
|
||||
|
||||
expect.extend({ toMatchImageSnapshot })
|
||||
|
||||
/* eslint-disable */
|
||||
describe('XSS', () => {
|
||||
it('should handle xss in tags', async () => {
|
||||
// const str = 'graph LR;\nB-->D(<img onerror=location=`javascript\u003aalert\u0028document.domain\u0029` src=x>);'
|
||||
const str = 'eyJjb2RlIjoiXG5ncmFwaCBMUlxuICAgICAgQi0tPkQoPGltZyBvbmVycm9yPWxvY2F0aW9uPWBqYXZhc2NyaXB0XFx1MDAzYXhzc0F0dGFja1xcdTAwMjhkb2N1bWVudC5kb21haW5cXHUwMDI5YCBzcmM9eD4pOyIsIm1lcm1haWQiOnsidGhlbWUiOiJkZWZhdWx0In19';
|
||||
await imgSnapshotTest(page, str,
|
||||
{}, true)
|
||||
})
|
||||
})
|