| 1 | import { imgSnapshotTest, mermaidUrl, utf8ToB64 } from '../../helpers/util.ts'; |
| 2 | describe('XSS', () => { |
| 3 | it('should handle xss in tags', () => { |
| 4 | const str = |
| 5 | 'eyJjb2RlIjoiXG5ncmFwaCBMUlxuICAgICAgQi0tPkQoPGltZyBvbmVycm9yPWxvY2F0aW9uPWBqYXZhc2NyaXB0XFx1MDAzYXhzc0F0dGFja1xcdTAwMjhkb2N1bWVudC5kb21haW5cXHUwMDI5YCBzcmM9eD4pOyIsIm1lcm1haWQiOnsidGhlbWUiOiJkZWZhdWx0In19'; |
| 6 | |
| 7 | const url = mermaidUrl(str, {}, true); |
| 8 | |
| 9 | cy.visit(url); |
| 10 | cy.wait(1000).then(() => { |
| 11 | cy.get('.mermaid').should('exist'); |
| 12 | }); |
| 13 | }); |
| 14 | |
| 15 | it('should not allow tags in the css', () => { |
| 16 | const str = |
| 17 | 'eyJjb2RlIjoiJSV7aW5pdDogeyAnZm9udEZhbWlseSc6ICdcXFwiPjwvc3R5bGU+PGltZyBzcmM9eCBvbmVycm9yPXhzc0F0dGFjaygpPid9IH0lJVxuZ3JhcGggTFJcbiAgICAgQSAtLT4gQiIsIm1lcm1haWQiOnsidGhlbWUiOiJkZWZhdWx0IiwiZmxvd2NoYXJ0Ijp7Imh0bWxMYWJlbHMiOmZhbHNlfX0sInVwZGF0ZUVkaXRvciI6ZmFsc2V9'; |
| 18 | |
| 19 | const url = mermaidUrl( |
| 20 | str, |
| 21 | { |
| 22 | theme: 'default', |
| 23 | flowchart: { |
| 24 | htmlMode: false, |
| 25 | }, |
| 26 | }, |
| 27 | true |
| 28 | ); |
| 29 | |
| 30 | cy.visit(url); |
| 31 | cy.wait(1000).then(() => { |
| 32 | cy.get('#the-malware').should('not.exist'); |
| 33 | }); |
| 34 | }); |
| 35 | |
| 36 | it('should handle xss in tags in non-html mode', () => { |
| 37 | const str = |
| 38 | 'eyJjb2RlIjoiXG5ncmFwaCBMUlxuICAgICAgQi0tPkQoPGltZyBvbmVycm9yPWxvY2F0aW9uPWBqYXZhc2NyaXB0XFx1MDAzYXhzc0F0dGFja1xcdTAwMjhkb2N1bWVudC5kb21haW5cXHUwMDI5YCBzcmM9eD4pOyIsIm1lcm1haWQiOnsidGhlbWUiOiJkZWZhdWx0IiwiZmxvd2NoYXJ0Ijp7Imh0bWxMYWJlbHMiOmZhbHNlfX19'; |
| 39 | |
| 40 | const url = mermaidUrl( |
| 41 | str, |
| 42 | { |
| 43 | theme: 'default', |
| 44 | flowchart: { |
| 45 | htmlMode: false, |
| 46 | }, |
| 47 | }, |
| 48 | true |
| 49 | ); |
| 50 | |
| 51 | cy.visit(url); |
| 52 | cy.wait(1000); |
| 53 | |
| 54 | cy.get('#the-malware').should('not.exist'); |
| 55 | }); |
| 56 | |
| 57 | it('should not allow changing the __proto__ attribute using config', () => { |
| 58 | cy.visit('/xss2.html'); |
| 59 | cy.wait(1000); |
| 60 | cy.get('#the-malware').should('not.exist'); |
| 61 | }); |
| 62 | it('should not allow manipulating htmlLabels into a false positive', () => { |
| 63 | cy.visit('/xss4.html'); |
| 64 | cy.wait(1000); |
| 65 | cy.get('#the-malware').should('not.exist'); |
| 66 | }); |
| 67 | it('should not allow manipulating antiscript to run javascript', () => { |
| 68 | cy.visit('/xss5.html'); |
| 69 | cy.wait(1000); |
| 70 | cy.get('#the-malware').should('not.exist'); |
| 71 | }); |
| 72 | it('should not allow manipulating antiscript to run javascript using onerror', () => { |
| 73 | cy.visit('/xss6.html'); |
| 74 | cy.wait(1000); |
| 75 | cy.get('#the-malware').should('not.exist'); |
| 76 | }); |
| 77 | it('should not allow manipulating antiscript to run javascript using onerror in state diagrams with dagre wrapper', () => { |
| 78 | cy.visit('/xss8.html'); |
| 79 | cy.wait(1000); |
| 80 | cy.get('#the-malware').should('not.exist'); |
| 81 | }); |
| 82 | it('should not allow manipulating antiscript to run javascript using onerror in state diagrams with dagre d3', () => { |
| 83 | cy.on('uncaught:exception', (_err, _runnable) => { |
| 84 | return false; // continue rendering even if there if mermaid throws an error |
| 85 | }); |
| 86 | cy.visit('/xss9.html'); |
| 87 | cy.wait(1000); |
| 88 | cy.get('#the-malware').should('not.exist'); |
| 89 | }); |
| 90 | it('should not allow manipulating antiscript to run javascript using onerror in state diagrams with dagre d3', () => { |
| 91 | cy.visit('/xss10.html'); |
| 92 | cy.wait(1000); |
| 93 | cy.get('#the-malware').should('not.exist'); |
| 94 | }); |
| 95 | it('should not allow manipulating antiscript to run javascript using onerror in state diagrams with dagre d3', () => { |
| 96 | cy.visit('/xss11.html'); |
| 97 | cy.wait(1000); |
| 98 | cy.get('#the-malware').should('not.exist'); |
| 99 | }); |
| 100 | it('should not allow manipulating antiscript to run javascript using onerror in state diagrams with dagre d3', () => { |
| 101 | cy.visit('/xss12.html'); |
| 102 | cy.wait(1000); |
| 103 | cy.get('#the-malware').should('not.exist'); |
| 104 | }); |
| 105 | it('should not allow manipulating antiscript to run javascript using onerror in state diagrams with dagre d3', () => { |
| 106 | cy.visit('/xss13.html'); |
| 107 | cy.wait(1000); |
| 108 | cy.get('#the-malware').should('not.exist'); |
| 109 | }); |
| 110 | it('should not allow manipulating antiscript to run javascript iframes in class diagrams', () => { |
| 111 | cy.visit('/xss14.html'); |
| 112 | cy.wait(1000); |
| 113 | cy.get('#the-malware').should('not.exist'); |
| 114 | }); |
| 115 | it('should sanitize cardinalities properly in class diagrams', () => { |
| 116 | cy.visit('/xss18.html'); |
| 117 | cy.wait(1000); |
| 118 | cy.get('#the-malware').should('not.exist'); |
| 119 | }); |
| 120 | it('should sanitize colons properly', () => { |
| 121 | cy.visit('/xss20.html'); |
| 122 | cy.wait(1000); |
| 123 | cy.get('a').click(''); |
| 124 | cy.wait(1000); |
| 125 | cy.get('#the-malware').should('not.exist'); |
| 126 | }); |
| 127 | it('should sanitize colons properly', () => { |
| 128 | cy.visit('/xss21.html'); |
| 129 | cy.wait(1000); |
| 130 | cy.get('a').click(''); |
| 131 | cy.wait(1000); |
| 132 | cy.get('#the-malware').should('not.exist'); |
| 133 | }); |
| 134 | it('should sanitize backticks in class names properly', () => { |
| 135 | cy.visit('/xss24.html'); |
| 136 | cy.wait(1000); |
| 137 | cy.get('#the-malware').should('not.exist'); |
| 138 | }); |
| 139 | it('should sanitize backticks block diagram labels properly', () => { |
| 140 | cy.visit('/xss25.html'); |
| 141 | cy.wait(1000); |
| 142 | cy.get('#the-malware').should('not.exist'); |
| 143 | }); |
| 144 | |
| 145 | it('should sanitize icon labels in architecture diagrams', () => { |
| 146 | const str = JSON.stringify({ |
| 147 | code: `architecture-beta |
| 148 | group api(cloud)[API] |
| 149 | service db "<img src=x onerror=\\"xssAttack()\\">" [Database] in api`, |
| 150 | }); |
| 151 | imgSnapshotTest(utf8ToB64(str), {}, true); |
| 152 | cy.wait(1000); |
| 153 | cy.get('#the-malware').should('not.exist'); |
| 154 | }); |
| 155 | |
| 156 | it('should sanitize katex blocks', () => { |
| 157 | const str = JSON.stringify({ |
| 158 | code: `sequenceDiagram |
| 159 | participant A as Alice<img src="x" onerror="xssAttack()">$$\\text{Alice}$$ |
| 160 | A->>John: Hello John, how are you?`, |
| 161 | }); |
| 162 | imgSnapshotTest(utf8ToB64(str), {}, true); |
| 163 | cy.wait(1000); |
| 164 | cy.get('#the-malware').should('not.exist'); |
| 165 | }); |
| 166 | |
| 167 | it('should sanitize labels', () => { |
| 168 | const str = JSON.stringify({ |
| 169 | code: `erDiagram |
| 170 | "<img src=x onerror=xssAttack()>" ||--|| ENTITY2 : "<img src=x onerror=xssAttack()>" |
| 171 | `, |
| 172 | }); |
| 173 | imgSnapshotTest(utf8ToB64(str), {}, true); |
| 174 | cy.wait(1000); |
| 175 | cy.get('#the-malware').should('not.exist'); |
| 176 | }); |
| 177 | }); |
| 178 | |