diff --git a/cypress/integration/loadSite.spec.ts b/cypress/integration/loadSite.spec.ts index 0c58d373..c83d6d14 100644 --- a/cypress/integration/loadSite.spec.ts +++ b/cypress/integration/loadSite.spec.ts @@ -29,4 +29,14 @@ describe('Site Loads', () => { cy.contains('Class Diagram').click(); cy.contains('classDiagram'); }); + + it('should prevent setting the "securityLevel" option via URL', () => { + const b64State = btoa( + `{"code":"graph TD\\nA[\\"\\"]","mermaid":"{\\"securityLevel\\": \\"loose\\", \\"theme\\": \\"forest\\"}","updateEditor":true,"autoSync":true,"updateDiagram":true}` + ); + cy.visit(`/edit#${b64State}`); + cy.contains('Config').click(); + cy.contains('forest').should('exist'); + cy.contains('securityLevel').should('not.exist'); + }); }); diff --git a/src/lib/components/view.svelte b/src/lib/components/view.svelte index bca08fd5..4263be68 100644 --- a/src/lib/components/view.svelte +++ b/src/lib/components/view.svelte @@ -5,7 +5,7 @@ import { onMount } from 'svelte'; import type { Mermaid } from 'mermaid'; - const mermaid: Mermaid = (window.mermaid as unknown) as Mermaid; + const mermaid: Mermaid = window.mermaid as unknown as Mermaid; let code = ''; let container: HTMLDivElement; let error = false; @@ -25,9 +25,7 @@ const scroll = container.parentElement.parentElement.parentElement.scrollTop; container.innerHTML = code; delete container.dataset.processed; - mermaid.initialize( - Object.assign({}, JSON.parse(state.mermaid), { securityLevel: 'strict' }) - ); // Monkey patch: force securityLevel: strict to mitigate XSS attacks + mermaid.initialize(Object.assign({}, JSON.parse(state.mermaid))); mermaid.render('graph-div', code, (svgCode) => { container.innerHTML = svgCode; }); diff --git a/src/lib/util/state.ts b/src/lib/util/state.ts index ebb839d5..9a599ccc 100644 --- a/src/lib/util/state.ts +++ b/src/lib/util/state.ts @@ -35,9 +35,11 @@ export const loadState = (data: string): void => { const stateStr = fromBase64(data); console.log(`Tring to load state: ${stateStr}`); state = JSON.parse(stateStr); - if (typeof state.mermaid !== 'string') { - state.mermaid = JSON.stringify(state.mermaid, null, 2); - } + const mermaidConfig = + typeof state.mermaid === 'string' ? JSON.parse(state.mermaid) : state.mermaid; + delete mermaidConfig.securityLevel; // Prevent setting overriding securityLevel when loading state to mitigate possible XSS attack + + state.mermaid = JSON.stringify(mermaidConfig, null, 2); } catch (e) { if (data) { console.error('Init error', e);