diff --git a/.changeset/brave-baths-behave.md b/.changeset/brave-baths-behave.md new file mode 100644 index 000000000..b688a1faf --- /dev/null +++ b/.changeset/brave-baths-behave.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +fix: Prevent HTML tags from being escaped in sandbox label rendering diff --git a/cypress/helpers/util.ts b/cypress/helpers/util.ts index 0332178f6..51268c2a9 100644 --- a/cypress/helpers/util.ts +++ b/cypress/helpers/util.ts @@ -98,12 +98,21 @@ export const openURLAndVerifyRendering = ( cy.visit(url); cy.window().should('have.property', 'rendered', true); - cy.get('svg').should('be.visible'); - // cspell:ignore viewbox - cy.get('svg').should('not.have.attr', 'viewbox'); - if (validation) { - cy.get('svg').should(validation); + // Handle sandbox mode where SVG is inside an iframe + if (options.securityLevel === 'sandbox') { + cy.get('iframe').should('be.visible'); + if (validation) { + cy.get('iframe').should(validation); + } + } else { + cy.get('svg').should('be.visible'); + // cspell:ignore viewbox + cy.get('svg').should('not.have.attr', 'viewbox'); + + if (validation) { + cy.get('svg').should(validation); + } } if (screenshot) { diff --git a/cypress/integration/rendering/flowchart-v2.spec.js b/cypress/integration/rendering/flowchart-v2.spec.js index 5ef32c269..cd3676fbf 100644 --- a/cypress/integration/rendering/flowchart-v2.spec.js +++ b/cypress/integration/rendering/flowchart-v2.spec.js @@ -79,6 +79,18 @@ describe('Flowchart v2', () => { { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } ); }); + it('6a: should render complex HTML in labels with sandbox security', () => { + imgSnapshotTest( + `flowchart TD + A[Christmas] -->|Get money| B(Go shopping) + B --> C{Let me think} + C -->|One| D[Laptop] + C -->|Two| E[iPhone] + C -->|Three| F[fa:fa-car Car] + `, + { securityLevel: 'sandbox', flowchart: { htmlLabels: true } } + ); + }); it('7: should render a flowchart when useMaxWidth is true (default)', () => { renderGraph( `flowchart TD diff --git a/packages/mermaid/src/diagrams/common/common.spec.ts b/packages/mermaid/src/diagrams/common/common.spec.ts index 3c7e0fdb8..edaf0b6dd 100644 --- a/packages/mermaid/src/diagrams/common/common.spec.ts +++ b/packages/mermaid/src/diagrams/common/common.spec.ts @@ -70,6 +70,31 @@ describe('Sanitize text', () => { }); expect(result).not.toContain('javascript:alert(1)'); }); + + it('should allow HTML tags in sandbox mode', () => { + const htmlStr = '
This is a bold text
'; + const result = sanitizeText(htmlStr, { + securityLevel: 'sandbox', + flowchart: { htmlLabels: true }, + }); + expect(result).toContain(''); + expect(result).toContain(''); + expect(result).toContain(''); + expect(result).toContain('
'); + }); + + it('should remove script tags in sandbox mode', () => { + const maliciousStr = 'Hello world
'; + const result = sanitizeText(maliciousStr, { + securityLevel: 'sandbox', + flowchart: { htmlLabels: true }, + }); + expect(result).not.toContain('