mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-26 10:49:38 +02:00
Merge pull request #2210 from mermaid-js/2209_safety
Combining Mermaids native sanitation with DOMPurify
This commit is contained in:
@@ -56,17 +56,11 @@ subgraph CompositeState
|
|||||||
|
|
||||||
end
|
end
|
||||||
</div>
|
</div>
|
||||||
<div class="mermaid3" style="width: 100%; height: 20%;">
|
|
||||||
stateDiagram-v2
|
|
||||||
state CompositeState {
|
|
||||||
state AnotherCompositeState1234567890 {
|
|
||||||
YourState
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
javascript:alert('XSS')
|
|
||||||
<div class="mermaid" style="width: 100%; height: 20%;">
|
<div class="mermaid" style="width: 100%; height: 20%;">
|
||||||
|
graph TD
|
||||||
|
A["<img src=`https://via.placeholder.com/64/`>"]
|
||||||
|
</div>
|
||||||
|
<div class="mermaid2" style="width: 100%; height: 20%;">
|
||||||
flowchart TD
|
flowchart TD
|
||||||
Link --> b
|
Link --> b
|
||||||
click Link href "javascript:alert('XSS')" "Tooltip for
|
click Link href "javascript:alert('XSS')" "Tooltip for
|
||||||
|
@@ -36,8 +36,36 @@ export const removeScript = (txt) => {
|
|||||||
return rs;
|
return rs;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const sanitizeText = (text) => {
|
const sanitizeMore = (text, config) => {
|
||||||
const txt = DOMPurify.sanitize(text);
|
let txt = text;
|
||||||
|
let htmlLabels = true;
|
||||||
|
if (
|
||||||
|
config.flowchart &&
|
||||||
|
(config.flowchart.htmlLabels === false || config.flowchart.htmlLabels === 'false')
|
||||||
|
) {
|
||||||
|
htmlLabels = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (htmlLabels) {
|
||||||
|
const level = config.securityLevel;
|
||||||
|
|
||||||
|
if (level === 'antiscript') {
|
||||||
|
txt = removeScript(txt);
|
||||||
|
} else if (level !== 'loose') {
|
||||||
|
// eslint-disable-line
|
||||||
|
txt = breakToPlaceholder(txt);
|
||||||
|
txt = txt.replace(/</g, '<').replace(/>/g, '>');
|
||||||
|
txt = txt.replace(/=/g, '=');
|
||||||
|
txt = placeholderToBreak(txt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return txt;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const sanitizeText = (text, config) => {
|
||||||
|
const txt = sanitizeMore(DOMPurify.sanitize(text), config);
|
||||||
|
|
||||||
return txt;
|
return txt;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -50,7 +78,9 @@ export const hasBreaks = (text) => {
|
|||||||
export const splitBreaks = (text) => {
|
export const splitBreaks = (text) => {
|
||||||
return text.split(/<br\s*[/]?>/gi);
|
return text.split(/<br\s*[/]?>/gi);
|
||||||
};
|
};
|
||||||
|
const placeholderToBreak = (s) => {
|
||||||
|
return s.replace(/#br#/g, '<br/>');
|
||||||
|
};
|
||||||
const breakToPlaceholder = (s) => {
|
const breakToPlaceholder = (s) => {
|
||||||
return s.replace(lineBreakRegex, '#br#');
|
return s.replace(lineBreakRegex, '#br#');
|
||||||
};
|
};
|
||||||
|
@@ -121,7 +121,7 @@ describe('[Singlenodes] when parsing', () => {
|
|||||||
|
|
||||||
expect(edges.length).toBe(0);
|
expect(edges.length).toBe(0);
|
||||||
expect(vert['a'].type).toBe('diamond');
|
expect(vert['a'].type).toBe('diamond');
|
||||||
expect(vert['a'].text).toBe('A <br> end');
|
expect(vert['a'].text).toBe('A <br/> end');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle a single hexagon node', function() {
|
it('should handle a single hexagon node', function() {
|
||||||
@@ -144,7 +144,7 @@ describe('[Singlenodes] when parsing', () => {
|
|||||||
|
|
||||||
expect(edges.length).toBe(0);
|
expect(edges.length).toBe(0);
|
||||||
expect(vert['a'].type).toBe('hexagon');
|
expect(vert['a'].type).toBe('hexagon');
|
||||||
expect(vert['a'].text).toBe('A <br> end');
|
expect(vert['a'].text).toBe('A <br/> end');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle a single round node with html in it', function() {
|
it('should handle a single round node with html in it', function() {
|
||||||
@@ -156,7 +156,7 @@ describe('[Singlenodes] when parsing', () => {
|
|||||||
|
|
||||||
expect(edges.length).toBe(0);
|
expect(edges.length).toBe(0);
|
||||||
expect(vert['a'].type).toBe('round');
|
expect(vert['a'].type).toBe('round');
|
||||||
expect(vert['a'].text).toBe('A <br> end');
|
expect(vert['a'].text).toBe('A <br/> end');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle a single node with alphanumerics starting on a char', function() {
|
it('should handle a single node with alphanumerics starting on a char', function() {
|
||||||
|
@@ -328,7 +328,7 @@ describe('[Text] when parsing', () => {
|
|||||||
const edges = flow.parser.yy.getEdges();
|
const edges = flow.parser.yy.getEdges();
|
||||||
|
|
||||||
expect(vert['C'].type).toBe('round');
|
expect(vert['C'].type).toBe('round');
|
||||||
expect(vert['C'].text).toBe('Chimpansen hoppar åäö <br> - ÅÄÖ');
|
expect(vert['C'].text).toBe('Chimpansen hoppar åäö <br/> - ÅÄÖ');
|
||||||
});
|
});
|
||||||
// xit('it should handle åäö, minus and space and br',function(){
|
// xit('it should handle åäö, minus and space and br',function(){
|
||||||
// const res = flow.parser.parse('graph TD; A[Object(foo,bar)]-->B(Thing);');
|
// const res = flow.parser.parse('graph TD; A[Object(foo,bar)]-->B(Thing);');
|
||||||
|
Reference in New Issue
Block a user